zoukankan      html  css  js  c++  java
  • jvm源码解读--01 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
  • 相关阅读:
    基于.net mvc 的供应链管理系统(YB-SCM)开发随笔1-开篇
    基于.net mvc 的供应链管理系统(YB-SCM)开发随笔
    asp.net http to https
    html嵌入音频
    语义化练习分区域
    html文档引用css使用外部样式表
    字体样式 圆角边框
    HTML-标签
    前端基础—客户端
    html初识form表单
  • 原文地址:https://www.cnblogs.com/zytcomeon/p/14576809.html
Copyright © 2011-2022 走看看