01、jvm源码解读 - jvm加载java-lang-object过程

现在做一下记录,这个看了两天,看的过程发现了很多c++的高级特性,没接触过,还得慢慢撸,禁止很慢

那么现在开始 吧

先打两个断点

java.c:351

JavaMain(void * _args)
{
    JavaMainArgs *args = (JavaMainArgs *)_args;

文件加载的断点

systemDictionary.cpp:1289

instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {

特别说明

如果你想在加载 特定名字的类class文件可以使用 break *** if $_streq(*,*)==0 来设断点 可参照我的上一篇文章

现在看下load_instance_class函数

instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
  instanceKlassHandle nh = instanceKlassHandle(); // null Handle
  if (class_loader.is_null()) {

    // Search the shared system dictionary for classes preloaded into the
    // shared spaces.
    instanceKlassHandle k;
    {
      PerfTraceTime vmtimer(ClassLoader::perf_shared_classload_time());
      k = load_shared_class(class_name, class_loader, THREAD);
    }

    if (k.is_null()) {
      // Use VM class loader
      PerfTraceTime vmtimer(ClassLoader::perf_sys_classload_time());
      k = ClassLoader::load_classfile(class_name, CHECK_(nh));
    }

    // find_or_define_instance_class may return a different InstanceKlass
    if (!k.is_null()) {
      k = find_or_define_instance_class(class_name, class_loader, k, CHECK_(nh));
    }
    return k;
  } else {
    // Use user specified class loader to load class. Call loadClass operation on class_loader.
    ResourceMark rm(THREAD);

    assert(THREAD->is_Java_thread(), "must be a JavaThread");
    JavaThread* jt = (JavaThread*) THREAD;

    PerfClassTraceTime vmtimer(ClassLoader::perf_app_classload_time(),
                               ClassLoader::perf_app_classload_selftime(),
                               ClassLoader::perf_app_classload_count(),
                               jt->get_thread_stat()->perf_recursion_counts_addr(),
                               jt->get_thread_stat()->perf_timers_addr(),
                               PerfClassTraceTime::CLASS_LOAD);

    Handle s = java_lang_String::create_from_symbol(class_name, CHECK_(nh));
    // Translate to external class name format, i.e., convert '/' chars to '.'
    Handle string = java_lang_String::externalize_classname(s, CHECK_(nh));

    JavaValue result(T_OBJECT);

    KlassHandle spec_klass (THREAD, SystemDictionary::ClassLoader_klass());
    if (MustCallLoadClassInternal && has_loadClassInternal()) {
      JavaCalls::call_special(&result,
                              class_loader,
                              spec_klass,
                              vmSymbols::loadClassInternal_name(),
                              vmSymbols::string_class_signature(),
                              string,
                              CHECK_(nh));
    } else {
      JavaCalls::call_virtual(&result,
                              class_loader,
                              spec_klass,
                              vmSymbols::loadClass_name(),
                              vmSymbols::string_class_signature(),
                              string,
                              CHECK_(nh));
    }

    assert(result.get_type() == T_OBJECT, "just checking");
    oop obj = (oop) result.get_jobject();

    // Primitive classes return null since forName() can not be
    // used to obtain any of the Class objects representing primitives or void
    if ((obj != NULL) && !(java_lang_Class::is_primitive(obj))) {
      instanceKlassHandle k =
                instanceKlassHandle(THREAD, java_lang_Class::as_Klass(obj));
      // For user defined Java class loaders, check that the name returned is
      // the same as that requested.  This check is done for the bootstrap
      // loader when parsing the class file.
      if (class_name == k->name()) {
        return k;
      }
    }
    // Class is not found or has the wrong name, return NULL
    return nh;
  }
}

先看这个函数的参数,参数Symbol* class_name

获取符号的名字

(gdb) p class_name->as_utf8()
$3 = 0x7faadc009d08 "java/lang/Object"

看Handle定义,重点是只有一个oop* 类型的指针

class Handle VALUE_OBJ_CLASS_SPEC {
 private:
  oop* _handle;

 protected:
  oop     obj() const                            { return _handle == NULL ? (oop)NULL : *_handle; }
  oop     non_null_obj() const                   { assert(_handle != NULL, "resolving NULL handle"); return *_handle; }

 public:
  // Constructors
  Handle()                                       { _handle = NULL; }
  Handle(oop obj);
  Handle(Thread* thread, oop obj);

  // General access
  oop     operator () () const                   { return obj(); }
  oop     operator -> () const                   { return non_null_obj(); }
  bool    operator == (oop o) const              { return obj() == o; }
  bool    operator == (const Handle& h) const          { return obj() == h.obj(); }

  // Null checks
  bool    is_null() const                        { return _handle == NULL; }
  bool    not_null() const                       { return _handle != NULL; }

  // Debugging
  void    print()                                { obj()->print(); }

  // Direct interface, use very sparingly.
  // Used by JavaCalls to quickly convert handles and to create handles static data structures.
  // Constructor takes a dummy argument to prevent unintentional type conversion in C++.
  Handle(oop *handle, bool dummy)                { _handle = handle; }

  // Raw handle access. Allows easy duplication of Handles. This can be very unsafe
  // since duplicates is only valid as long as original handle is alive.
  oop* raw_value()                               { return _handle; }
  static oop raw_resolve(oop *handle)            { return handle == NULL ? (oop)NULL : *handle; }
};

其中参数赋值在这里,这个是 构造函数来创建对象

Klass* SystemDictionary::resolve_or_fail(Symbol* class_name,
                                           bool throw_error, TRAPS)
{
  return resolve_or_fail(class_name, Handle(), Handle(), throw_error, THREAD);
}

所以此时的oop* 类型的指针=null

进入接下来的流程

//流程
instanceKlassHandle SystemDictionary::load_shared_class(
                 Symbol* class_name, Handle class_loader, TRAPS) {
  instanceKlassHandle ik (THREAD, find_shared_class(class_name));//ik的构造函数,这个是隐式构造函数
  return load_shared_class(ik, class_loader, THREAD);//if (ik->super() != NULL) {}不满足,因为ik是null 就直接返回了ik
}
};
{
instanceKlassHandle ik (THREAD, find_shared_class(class_name)); //find_shared_class(class_name)=null
};

{
  instanceKlassHandle (Thread* thread, const Klass* k) : KlassHandle(thread, k) { //:后面是调用父类构造方法
    assert(k == NULL || k->oop_is_instance(),
           "illegal type");
  }
};

在补充KlassHandle定义

class KlassHandle : public StackObj {
  Klass* _value;
 protected:
   Klass* obj() const          { return _value; }
   Klass* non_null_obj() const { assert(_value != NULL, "resolving NULL _value"); return _value; }

 public:
   KlassHandle()                                 : _value(NULL) {}
   KlassHandle(const Klass* obj)                 : _value(const_cast<Klass *>(obj)) {};
   KlassHandle(Thread* thread, const Klass* obj) : _value(const_cast<Klass *>(obj)) {};//构造方法, _value(xxx)初始化列表

   Klass* operator () () const { return obj(); }
   Klass* operator -> () const { return non_null_obj(); }

   bool operator == (Klass* o) const             { return obj() == o; }
   bool operator == (const KlassHandle& h) const { return obj() == h.obj(); }

    bool is_null() const  { return _value == NULL; }
    bool not_null() const { return _value != NULL; }
};

接着

instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
  instanceKlassHandle nh = instanceKlassHandle(); // null Handle
  if (class_loader.is_null()) {

    // Search the shared system dictionary for classes preloaded into the
    // shared spaces.
    instanceKlassHandle k;
    {
      PerfTraceTime vmtimer(ClassLoader::perf_shared_classload_time());
      k = load_shared_class(class_name, class_loader, THREAD);
    }

    if (k.is_null()) { //进入到这里,执行到这里,klass是null
      // Use VM class loader
      PerfTraceTime vmtimer(ClassLoader::perf_sys_classload_time());
      k = ClassLoader::load_classfile(class_name, CHECK_(nh));
    }
....
}

/进入加载文件

instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) {
  ResourceMark rm(THREAD);
  EventMark m("loading class %s", h_name->as_C_string());
  ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion);

  stringStream st;
  // st.print() uses too much stack space while handling a StackOverflowError
  // st.print("%s.class", h_name->as_utf8());
  st.print_raw(h_name->as_utf8()); //这里能打印 name的字符串
  st.print_raw(".class");
  char* name = st.as_string(); //结果为:=>"java/lang/Object.class"

  // Lookup stream for parsing .class file
  ClassFileStream* stream = NULL;
  int classpath_index = 0;
  {
    PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(),
                               ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(),
                               PerfClassTraceTime::CLASS_LOAD);
    ClassPathEntry* e = _first_entry; //$6 = (LazyClassPathEntry *) 0x7faadc01a108
    while (e != NULL) {
      stream = e->open_stream(name, CHECK_NULL);
      if (stream != NULL) {
        break;
      }
      e = e->next();
      ++classpath_index;
    }
  }

  instanceKlassHandle h;
  if (stream != NULL) {

    // class file found, parse it
    ClassFileParser parser(stream);
    ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
    Handle protection_domain;
    TempNewSymbol parsed_name = NULL;
    instanceKlassHandle result = parser.parseClassFile(h_name,
                                                       loader_data,
                                                       protection_domain,
                                                       parsed_name,
                                                       false,
                                                       CHECK_(h));

    // add to package table
    if (add_package(name, classpath_index, THREAD)) {
      h = result;
    }
  }

  return h;
}

ClassPathEntry这个类定义

class ClassPathEntry: public CHeapObj<mtClass> {
 private:
  ClassPathEntry* _next;
 public:
  // Next entry in class path
  ClassPathEntry* next()              { return _next; }
  void set_next(ClassPathEntry* next) {
    // may have unlocked readers, so write atomically.
    OrderAccess::release_store_ptr(&_next, next);
  }
  virtual bool is_jar_file() = 0;
  virtual const char* name() = 0;
  virtual bool is_lazy();
  // Constructor
  ClassPathEntry();
  // Attempt to locate file_name through this class path entry.
  // Returns a class file parsing stream if successfull.
  virtual ClassFileStream* open_stream(const char* name, TRAPS) = 0;
  // Debugging
  NOT_PRODUCT(virtual void compile_the_world(Handle loader, TRAPS) = 0;)
  NOT_PRODUCT(virtual bool is_rt_jar() = 0;)
};

进入方法

ClassFileStream* LazyClassPathEntry::open_stream(const char* name, TRAPS) {
  if (_meta_index != NULL &&
      !_meta_index->may_contain(name)) {
    return NULL;
  }
  if (_has_error) {
    return NULL;
  }
  ClassPathEntry* cpe = resolve_entry(THREAD);
  if (cpe == NULL) {
    _has_error = true;
    return NULL;
  } else {
    return cpe->open_stream(name, THREAD);//直接进入这里上边的if条件没有满足的
  }
}

接着进入

ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) { //name为 $7 = 0x7faadc009ea8 "java/lang/Object.class"
  // enable call to C land
  JavaThread* thread = JavaThread::current();
  ThreadToNativeFromVM ttn(thread);
  // check whether zip archive contains name
  jint filesize, name_len;
  jzentry* entry = (*FindEntry)(_zip, name, &filesize, &name_len);//这里返回null,结束代码
  if (entry == NULL) return NULL;
  u1* buffer;
  char name_buf[128];
  char* filename;
  if (name_len < 128) {
    filename = name_buf;
  } else {
    filename = NEW_RESOURCE_ARRAY(char, name_len + 1);
  }

  // file found, get pointer to class in mmaped jar file.
  if (ReadMappedEntry == NULL ||
      !(*ReadMappedEntry)(_zip, entry, &buffer, filename)) {
      // mmaped access not available, perhaps due to compression,
      // read contents into resource array
      buffer     = NEW_RESOURCE_ARRAY(u1, filesize);
      if (!(*ReadEntry)(_zip, entry, buffer, filename)) return NULL;
  }
  if (UsePerfData) {
    ClassLoader::perf_sys_classfile_bytes_read()->inc(filesize);
  }
  // return result
  return new ClassFileStream(buffer, filesize, _zip_name);    // Resource allocated
}

以上是在jce.jar来查找java/lang/Object.Class,找不到就在下个循环来找

返回进入第二个循环,再次进入open_stream,但是你留心看发现进入的是ClassPathDirEntry,上一次进入的是ZIPEntry,是多态的体现

ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) {
  // construct full path name
  /**
   *    (gdb) p _dir
        $9 = 0x7faadc06ebb8 "/home/atzhang/atzhang/openjdksource/openjdk8/openjdk/build/linux-x86_64-normal-server-slowdebug/jdk/classes"
   **/ 
  char path[JVM_MAXPATHLEN];
  if (jio_snprintf(path, sizeof(path), "%s%s%s", _dir, os::file_separator(), name) == -1) {//拼接文件夹和目标类名
    return NULL;
  }
  //(gdb) x/40s path
  //0x7faae3a1cdb0:    "/home/atzhang/atzhang/openjdksource/openjdk8/openjdk/build/linux-x86_64-normal-server-slowdebug/jdk/classes/java/lang/Object.class"

  // check if file exists
  struct stat st;                  //声明结构体固定格式 struct 结构体类型  变量名
  if (os::stat(path, &st) == 0) {
    // found file, open it
    int file_handle = os::open(path, 0, 0);
    if (file_handle != -1) {
      // read contents into resource array
      u1* buffer = NEW_RESOURCE_ARRAY(u1, st.st_size);
      //函数说明:read()会把参数fd所指的文件传送count 个字节到buf 指针所指的内存中。
      size_t num_read = os::read(file_handle, (char*) buffer, st.st_size); //st_size 以字节为单位的文件容量=1734
      // close file
      os::close(file_handle); //关闭文件
      // construct ClassFileStream
      if (num_read == (size_t)st.st_size) {
        if (UsePerfData) {
          ClassLoader::perf_sys_classfile_bytes_read()->inc(num_read);
        }
        return new ClassFileStream(buffer, st.st_size, _dir);    // Resource allocated
      }
    }
  }
  return NULL;
}

补充类定义

ClassPathDirEntry {
private:
  char* _dir;           // Name of directory
 public:
  bool is_jar_file()  { return false;  }
  const char* name()  { return _dir; }
  ClassPathDirEntry(char* dir);
  ClassFileStream* open_stream(const char* name, TRAPS);
  // Debugging
  NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
  NOT_PRODUCT(bool is_rt_jar();)
};

看重点(黄色标记的)

//重点看
{
  struct stat st;
  if (os::stat(path, &st) == 0) {} //获取文件信息
}
(gdb) p/x st
$9 = {st_dev = 0xfd00, st_ino = 0x17b9b78, st_nlink = 0x1, st_mode = 0x81a4, st_uid = 0x0, st_gid = 0x0, __pad0 = 0x0, st_rdev = 0x0, st_size = 0x6c6, st_blksize = 0x1000, st_blocks = 0x8, st_atim = {tv_sec = 0x605bf569, tv_nsec = 0x36eea242}, st_mtim = {tv_sec = 0x60588cf6, tv_nsec = 0x2ff50a69}, st_ctim = {tv_sec = 0x60588cf6, tv_nsec = 0x2ff50a69}, __unused = {0x0, 0x0, 0x0}}

能看到stat是linux的系统函数,介绍如下

stat函数 ​ 作用:获取文件信息  函数原型:int stat(const char *path, struct stat *buf)
​ 返回值:成功返回0,失败返回-1; ​ 参数:文件路径(名),struct stat 类型的结构体

struct stat
{
    dev_t     st_dev;     /* ID of device containing file */文件使用的设备号
    ino_t     st_ino;     /* inode number */    索引节点号 
    mode_t    st_mode;    /* protection */  文件对应的模式,文件,目录等
    nlink_t   st_nlink;   /* number of hard links */    文件的硬连接数  
    uid_t     st_uid;     /* user ID of owner */    所有者用户识别号
    gid_t     st_gid;     /* group ID of owner */   组识别号  
    dev_t     st_rdev;    /* device ID (if special file) */ 设备文件的设备号
    off_t     st_size;    /* total size, in bytes */ 以字节为单位的文件容量   
    blksize_t st_blksize; /* blocksize for file system I/O */ 包含该文件的磁盘块的大小   
    blkcnt_t  st_blocks;  /* number of 512B blocks allocated */ 该文件所占的磁盘块  
    time_t    st_atime;   /* time of last access */ 最后一次访问该文件的时间   
    time_t    st_mtime;   /* time of last modification */ /最后一次修改该文件的时间   
    time_t    st_ctime;   /* time of last status change */ 最后一次改变该文件状态的时间   
};

stat结构体中的st_mode 则定义了下列数种情况:

    S_IFMT   0170000    文件类型的位遮罩
    S_IFSOCK 0140000    套接字
    S_IFLNK 0120000     符号连接
    S_IFREG 0100000     一般文件
    S_IFBLK 0060000     区块装置
    S_IFDIR 0040000     目录
    S_IFCHR 0020000     字符装置
    S_IFIFO 0010000     先进先出
​
    S_ISUID 04000     文件的(set user-id on execution)位
    S_ISGID 02000     文件的(set group-id on execution)位
    S_ISVTX 01000     文件的sticky位
​
    S_IRUSR(S_IREAD) 00400     文件所有者具可读取权限
    S_IWUSR(S_IWRITE)00200     文件所有者具可写入权限
    S_IXUSR(S_IEXEC) 00100     文件所有者具可执行权限
​
    S_IRGRP 00040             用户组具可读取权限
    S_IWGRP 00020             用户组具可写入权限
    S_IXGRP 00010             用户组具可执行权限
​
    S_IROTH 00004             其他用户具可读取权限
    S_IWOTH 00002             其他用户具可写入权限
    S_IXOTH 00001             其他用户具可执行权限
​
    上述的文件类型在POSIX中定义了检查这些类型的宏定义:
    S_ISLNK (st_mode)    判断是否为符号连接
    S_ISREG (st_mode)    是否为一般文件
    S_ISDIR (st_mode)    是否为目录
    S_ISCHR (st_mode)    是否为字符装置文件
    S_ISBLK (s3e)        是否为先进先出
    S_ISSOCK (st_mode)   是否为socket
    若一目录具有sticky位(S_ISVTX),则表示在此目录下的文件只能被该文件所有者、此目录所有者或root来删除或改名,在linux中,最典型的就是这个/tmp目录啦。
​
st_mode 的结构

st_mode 主要包含了 3 部分信息:

15-12 位保存文件类型

11-9 位保存执行文件时设置的信息

8-0 位保存文件访问权限

可以通过参照来解读文件信息

接着看打开文件,读取文件,关闭文件

    int file_handle = os::open(path, 0, 0);
    if (file_handle != -1) {
      // read contents into resource array
      u1* buffer = NEW_RESOURCE_ARRAY(u1, st.st_size);
      //函数说明:read()会把参数fd所指的文件传送count 个字节到buf 指针所指的内存中。
      size_t num_read = os::read(file_handle, (char*) buffer, st.st_size); //st_size 以字节为单位的文件容量=1734
      // close file
      os::close(file_handle); //关闭文件

接着看

      // construct ClassFileStream
      if (num_read == (size_t)st.st_size) {
        if (UsePerfData) {
          ClassLoader::perf_sys_classfile_bytes_read()->inc(num_read);
        }
        return new ClassFileStream(buffer, st.st_size, _dir);    // Resource allocated
      }

if成立,看UsePerfData

globals.hpp

#define RUNTIME_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct, manageable, product_rw, lp64_product) \
                                                                            \
  lp64_product(bool, UseCompressedOops, false,                              \
          "Use 32-bit object references in 64-bit VM. "                     \
          "lp64_product means flag is always constant in 32 bit VM")        \
  ...
  product(bool, UsePerfData, falseInEmbedded,                               \
          "Flag to disable jvmstat instrumentation for performance testing "\
          "and problem isolation purposes")                                 \
 ...                                               
#define falseInEmbedded true

那么条件等于true进入里面

static PerfCounter* perf_sys_classfile_bytes_read() { return _perf_sys_classfile_bytes_read; }

还有

class PerfLongVariant : public PerfLong {

  protected:
    jlong* _sampled;
    PerfLongSampleHelper* _sample_helper;

    PerfLongVariant(CounterNS ns, const char* namep, Units u, Variability v,
                    jlong initial_value=0)
                   : PerfLong(ns, namep, u, v) {
      if (is_valid()) *(jlong*)_valuep = initial_value;
    }

    PerfLongVariant(CounterNS ns, const char* namep, Units u, Variability v,
                    jlong* sampled);

    PerfLongVariant(CounterNS ns, const char* namep, Units u, Variability v,
                    PerfLongSampleHelper* sample_helper);

    void sample();

  public:
    inline void inc() { (*(jlong*)_valuep)++; }
    inline void inc(jlong val) { (*(jlong*)_valuep) += val; }
    inline void add(jlong val) { (*(jlong*)_valuep) += val; }
    void clear_sample_helper() { _sample_helper = NULL; }
};

将值加上173几

接着进入

return new ClassFileStream(buffer, st.st_size, _dir);    // Resource allocated

其中的参数

_dir 是

class ClassPathDirEntry: public ClassPathEntry {
 private:
  char* _dir;           // Name of directory

(gdb) p _dir
$10= 0x7f56d806eb98 "/home/atzhang/atzhang/openjdksource/openjdk8/openjdk/build/linux-x86_64-normal-server-slowdebug/jdk/classes"

(gdb) p st.st_size
$11= 1734 =0x6c6 其实地址为 0x7f56d800ea28 结束地址为 ea28 +6c6 =f0ee

buffer 是字节码文件

(gdb) x/1734x buffer
0x7f56d800ea28:    0xbebafeca    0x34000000    0x00075700    0x01000a3a
0x7f56d800ea38:    0x000a3b00    0x0a3c0012    0x3e003d00    0x0001000a
0x7f56d800ea48:    0x4000083f    0x0012000a    0x42000a41    0x000a4300
0x7f56d800ea58:    0x07440001    0x00084500    0x0a000a46    0x00034700
0x7f56d800ea68:    0x083f420f    0x00034800    0x0a20a107    0x49001200
0x7f56d800ea78:    0x0012000a    0x4b00074a    0x3c060001    0x74696e69
0x7f56d800ea88:    0x0300013e    0x01562928    0x6f430400    0x00016564
0x7f56d800ea98:    0x6e694c0f    0x6d754e65    0x54726562    0x656c6261
0x7f56d800eaa8:    0x4c120001    0x6c61636f    0x69726156    0x656c6261
0x7f56d800eab8:    0x6c626154    0x04000165    0x73696874    0x4c120001
0x7f56d800eac8:    0x6176616a    0x6e616c2f    0x624f2f67    0x7463656a
0x7f56d800ead8:    0x0f00013b    0x69676572    0x72657473    0x6974614e
0x7f56d800eae8:    0x01736576    0x65670800    0x616c4374    0x00017373
0x7f56d800eaf8:    0x4c292813    0x6176616a    0x6e616c2f    0x6c432f67
0x7f56d800eb08:    0x3b737361    0x53090001    0x616e6769    0x65727574
0x7f56d800eb18:    0x28160001    0x616a4c29    0x6c2f6176    0x2f676e61
0x7f56d800eb28:    0x73616c43    0x3e2a3c73    0x0800013b    0x68736168
0x7f56d800eb38:    0x65646f43    0x28030001    0x00014929    0x75716506
0x7f56d800eb48:    0x01736c61    0x4c281500    0x6176616a    0x6e616c2f
0x7f56d800eb58:    0x624f2f67    0x7463656a    0x015a293b    0x626f0300
0x7f56d800eb68:    0x0d00016a    0x63617453    0x70614d6b    0x6c626154
0x7f56d800eb78:    0x05000165    0x6e6f6c63    0x14000165    0x6a4c2928
0x7f56d800eb88:    0x2f617661    0x676e616c    0x6a624f2f    0x3b746365
0x7f56d800eb98:    0x450a0001    0x70656378    0x6e6f6974    0x4c000773
0x7f56d800eba8:    0x74080001    0x7274536f    0x01676e69    0x29281400
0x7f56d800ebb8:    0x76616a4c    0x616c2f61    0x532f676e    0x6e697274
0x7f56d800ebc8:    0x00013b67    0x746f6e06    0x01796669    0x6f6e0900
0x7f56d800ebd8:    0x79666974    0x016c6c41    0x61770400    0x00017469
0x7f56d800ebe8:    0x294a2804    0x4d000756    0x28050001    0x5629494a
0x7f56d800ebf8:    0x74070001    0x6f656d69    0x00017475    0x00014a01
0x7f56d800ec08:    0x6e616e05    0x0001736f    0x00014901    0x6e696608
0x7f56d800ec18:    0x7a696c61    0x4e000765    0x3c080001    0x6e696c63
0x7f56d800ec28:    0x013e7469    0x6f530a00    0x65637275    0x656c6946
0x7f56d800ec38:    0x4f0b0001    0x63656a62    0x616a2e74    0x00016176
0x7f56d800ec48:    0x76616a17    0x616c2f61    0x532f676e    0x6e697274
0x7f56d800ec58:    0x69754267    0x7265646c    0x0013000c    0x1b000c14
0x7f56d800ec68:    0x00071c00    0x50000c4f    0x000c2a00    0x01520051
0x7f56d800ec78:    0x0c400100    0x20001f00    0x0c530007    0x55005400
0x7f56d800ec88:    0x0029000c    0x2200012a    0x6176616a    0x6e616c2f
0x7f56d800ec98:    0x6c492f67    0x6167656c    0x6772416c    0x6e656d75
0x7f56d800eca8:    0x63784574    0x69747065    0x00016e6f    0x6d697419
0x7f56d800ecb8:    0x74756f65    0x6c617620    0x69206575    0x656e2073
0x7f56d800ecc8:    0x69746167    0x000c6576    0x01560013    0x616e2500
0x7f56d800ecd8:    0x65736f6e    0x646e6f63    0x6d697420    0x74756f65
0x7f56d800ece8:    0x6c617620    0x6f206575    0x6f207475    0x61722066
0x7f56d800ecf8:    0x0c65676e    0x2e002d00    0x001a000c    0x10000114
0x7f56d800ed08:    0x6176616a    0x6e616c2f    0x624f2f67    0x7463656a
0x7f56d800ed18:    0x6a240001    0x2f617661    0x676e616c    0x6f6c432f
0x7f56d800ed28:    0x6f4e656e    0x70755374    0x74726f70    0x78456465
0x7f56d800ed38:    0x74706563    0x016e6f69    0x616a1e00    0x6c2f6176
0x7f56d800ed48:    0x2f676e61    0x65746e49    0x70757272    0x45646574
0x7f56d800ed58:    0x70656378    0x6e6f6974    0x6a130001    0x2f617661
0x7f56d800ed68:    0x676e616c    0x7268542f    0x6261776f    0x0001656c
0x7f56d800ed78:    0x76616a0f    0x616c2f61    0x432f676e    0x7373616c
0x7f56d800ed88:    0x67070001    0x614e7465    0x0001656d    0x70706106
0x7f56d800ed98:    0x01646e65    0x4c282d00    0x6176616a    0x6e616c2f
0x7f56d800eda8:    0x74532f67    0x676e6972    0x6a4c293b    0x2f617661
0x7f56d800edb8:    0x676e616c    0x7274532f    0x42676e69    0x646c6975
0x7f56d800edc8:    0x013b7265    0x616a1100    0x6c2f6176    0x2f676e61
0x7f56d800edd8:    0x65746e49    0x01726567    0x6f740b00    0x53786548
0x7f56d800ede8:    0x6e697274    0x15000167    0x4c294928    0x6176616a
0x7f56d800edf8:    0x6e616c2f    0x74532f67    0x676e6972    0x1500013b
0x7f56d800ee08:    0x616a4c28    0x6c2f6176    0x2f676e61    0x69727453
0x7f56d800ee18:    0x293b676e    0x00210056    0x00000012    0x00000000
0x7f56d800ee28:    0x0001000e    0x00140013    0x00150001    0x002b0000
0x7f56d800ee38:    0x00010000    0xb1010000    0x02000000    0x00001600
0x7f56d800ee48:    0x01000600    0x25000000    0x00001700    0x01000c00
0x7f56d800ee58:    0x01000000    0x19001800    0x0a010000    0x14001a00
0x7f56d800ee68:    0x11010000    0x1c001b00    0x1d000100    0x02000000
0x7f56d800ee78:    0x01011e00    0x20001f00    0x01000000    0x22002100
0x7f56d800ee88:    0x15000100    0x4a000000    0x02000200    0x0b000000
0x7f56d800ee98:    0x00a62b2a    0x00a70407    0x00ac0304    0x00030000
0x7f56d800eea8:    0x00000016    0x00010006    0x00950000    0x00000017
0x7f56d800eeb8:    0x00020016    0x000b0000    0x00190018    0x00000000
0x7f56d800eec8:    0x0023000b    0x00010019    0x00000024    0x09020005
0x7f56d800eed8:    0x04010140    0x26002500    0x27000100    0x04000000
0x7f56d800eee8:    0x28000100    0x29000100    0x01002a00    0x00001500
0x7f56d800eef8:    0x02004e00    0x00000100    0x00bb2400    0x00b75901
0x7f56d800ef08:    0x00b62a02    0x0400b603    0x120500b6    0x0500b606
0x7f56d800ef18:    0x0700b62a    0xb60800b8    0x00b60500    0x0000b009
0x7f56d800ef28:    0x16000200    0x06000000    0x00000100    0x1700ec00
0x7f56d800ef38:    0x0c000000    0x00000100    0x18002400    0x00001900
0x7f56d800ef48:    0x2b001101    0x00001400    0x2c001101    0x00001400
0x7f56d800ef58:    0x2d001101    0x01002e00    0x00002700    0x01000400
0x7f56d800ef68:    0x11002f00    0x30002d00    0x15000200    0xa5000000
0x7f56d800ef78:    0x04000400    0x3e000000    0x9c94091f    0x00bb0d00
0x7f56d800ef88:    0x0b12590a    0xbf0c00b7    0x09009b1d    0xa40d121d
0x7f56d800ef98:    0x00bb0d00    0x0e12590a    0xbf0c00b7    0xa20f121d
0x7f56d800efa8:    0x991d0d00    0x091f0d00    0x07009a94    0x40610a1f
0x7f56d800efb8:    0x00b61f2a    0x0000b110    0x16000300    0x22000000
0x7f56d800efc8:    0x00000800    0x0600bf01    0x1000c001    0x1a00c301
0x7f56d800efd8:    0x2400c401    0x3400c801    0x3800c901    0x3d00cc01
0x7f56d800efe8:    0x1700cd01    0x20000000    0x00000300    0x18003e00
0x7f56d800eff8:    0x00001900    0x3e000000    0x32003100    0x00000100
0x7f56d800f008:    0x33003e00    0x03003400    0x00002400    0x05000700
0x7f56d800f018:    0x0f090910    0x00270003    0x00040000    0x002f0001
0x7f56d800f028:    0x002d0011    0x00020014    0x00000015    0x00030034
0x7f56d800f038:    0x00000001    0xb6092a06    0x00b11000    0x00020000
0x7f56d800f048:    0x00000016    0x0002000a    0x00f60100    0x00f70105
0x7f56d800f058:    0x00000017    0x0001000c    0x00060000    0x00190018
0x7f56d800f068:    0x00270000    0x00040000    0x002f0001    0x00350004
0x7f56d800f078:    0x00020014    0x00000015    0x0000002b    0x00000001
0x7f56d800f088:    0x0000b101    0x16000200    0x06000000    0x00000100
0x7f56d800f098:    0x17002b02    0x0c000000    0x00000100    0x18000100
0x7f56d800f0a8:    0x00001900    0x00002700    0x01000400    0x08003600
0x7f56d800f0b8:    0x14003700    0x15000100    0x20000000    0x00000000
0x7f56d800f0c8:    0x04000000    0xb11100b8    0x01000000    0x00001600
0x7f56d800f0d8:    0x02000a00    0x29000000    0x2a000300    0x38000100
0x7f56d800f0e8:    0x02000000    0xabab3900    0xabababab    0xabababab

今天到此结束

具体之中有有许多细节总结下

1、 c++构造方法;

子类构造方法:父类构造方法{

}

2、 结构体的生命;

struct stat st; //c必须有struct来声明
stat st;// c++可以可以省略struct

3、 使用构造方法来建造对象;

return resolve_or_fail(class_name, Handle(), Handle(), throw_error, THREAD);

4、 使用gdb的内置函数来设置断点条件;

if $_strcmp("hello","hello")==00

if $_memcmp(参数1,参数2)==00