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