龙空技术网

MacOS下JVM调试执行JAR包

会飞的石头926 120

前言:

而今咱们对“was查看jvm使用情况”大致比较重视,姐妹们都想要剖析一些“was查看jvm使用情况”的相关资讯。那么小编在网络上网罗了一些有关“was查看jvm使用情况””的相关内容,希望同学们能喜欢,大家快快来了解一下吧!

通过上一节介绍的编译过程,JVM的源码已经拉下来了。那么一个JAR包是如何运行的,如何能够通过调试JVM源码看到JAR的整个解析,初始化,执行等过程

1 导入源码

首先查看一下通过hg克隆下来的jvm源码包目录下的内容

截图中的文件夹

其中截图中build是上一节中编译结果。源码内容在hotspot中。这里通过CLion来导入源码。操作截图如上

选择hotspot目录即可。导入后的结果截图如下:

2 测试执行JAR包

编写测试JAR包这个简单构造一个就好。这里直接贴图和POM

pom文件内容如下:

<?xml version="1.0" encoding="UTF-8"?><project xmlns="" xmlns:xsi="" xsi:schemaLocation=" "> <modelVersion>4.0.0</modelVersion>​ <groupId>com.jvm.study.test</groupId> <artifactId>jvm-test</artifactId> <version>1.0-SNAPSHOT</version>​ <build> <finalName>jvm-test</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <mainClass>com.jvm.study.test.TestMain</mainClass> </manifest> </archive> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> </plugin> </plugins> </build>​</project>

使用mvn打包:

mvn clean package -DskipTests

打出来的依赖包:

/data/code/jvm-test/target/jvm-test.jar

使用JVM源码执行当前编译打出来的jar包:

启动Debug。

启动后,查看控制台,可以看到TestMain中打印的HelloWorld。已经打印出来了。

3 源码调试

经过第一篇文章介绍的内容,java源码会先编译为字节码文件,根据第二篇文章的内容可以看到字节码文件会被加载到内存中,并进行过多步操作实例化等。那么我们通过上面的测试jar包来看看字节码文件的解析,class类对象的实例化等过程是如何实现的。

Java中的defineClass1方法是个native方法,说明依赖于底层的实现,在HotSpot中,其实现位于ClassLoader.c文件中,最终调用jvm.cpp中的jvm_define_class_common方法实现,核心的实现逻辑如下:

从上面的截图可以看到整个jar包路径都已经加载进来了。下面开始做什么呢:

1 验证全限定类名的长度2 验证字节码格式内容

验证全限定类名长度

下面是开始解析验证字节码文件结构

根据调用过程我们单个函数看一下,先看一下parse_stream:

void ClassFileParser::parse_stream(const ClassFileStream* const stream, TRAPS) {​ assert(stream != NULL, "invariant"); assert(_class_name != NULL, "invariant");​ // BEGIN STREAM PARSING stream->guarantee_more(8, CHECK); // magic, major, minor // Magic value const u4 magic = stream->get_u4_fast(); guarantee_property(magic == JAVA_CLASSFILE_MAGIC, "Incompatible magic value %u in class file %s", magic, CHECK);​ // Version numbers _minor_version = stream->get_u2_fast(); _major_version = stream->get_u2_fast();​ if (DumpSharedSpaces && _major_version < JAVA_1_5_VERSION) { ResourceMark rm; warning("Pre JDK 1.5 class not supported by CDS: %u.%u %s", _major_version, _minor_version, _class_name->as_C_string()); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_UnsupportedClassVersionError(), "Unsupported major.minor version for dump time %u.%u", _major_version, _minor_version); }​ // Check version numbers - we check this even with verifier off if (!is_supported_version(_major_version, _minor_version)) { ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_UnsupportedClassVersionError(), "%s has been compiled by a more recent version of the Java Runtime (class file version %u.%u), " "this version of the Java Runtime only recognizes class file versions up to %u.%u", _class_name->as_C_string(), _major_version, _minor_version, JAVA_MAX_SUPPORTED_VERSION, JAVA_MAX_SUPPORTED_MINOR_VERSION); return; }​ stream->guarantee_more(3, CHECK); // length, first cp tag const u2 cp_size = stream->get_u2_fast();​ guarantee_property( cp_size >= 1, "Illegal constant pool size %u in class file %s", cp_size, CHECK);​ _cp = ConstantPool::allocate(_loader_data, cp_size, CHECK);​ ConstantPool* const cp = _cp;​ parse_constant_pool(stream, cp, cp_size, CHECK);​ assert(cp_size == (const u2)cp->length(), "invariant");​ // ACCESS FLAGS stream->guarantee_more(8, CHECK); // flags, this_class, super_class, infs_len​ // Access flags jint flags; // JVM_ACC_MODULE is defined in JDK-9 and later. if (_major_version >= JAVA_9_VERSION) { flags = stream->get_u2_fast() & (JVM_RECOGNIZED_CLASS_MODIFIERS | JVM_ACC_MODULE); } else { flags = stream->get_u2_fast() & JVM_RECOGNIZED_CLASS_MODIFIERS; }​ if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION) { // Set abstract bit for old class files for backward compatibility flags |= JVM_ACC_ABSTRACT; }​ verify_legal_class_modifiers(flags, CHECK);​ short bad_constant = class_bad_constant_seen(); if (bad_constant != 0) { // Do not throw CFE until after the access_flags are checked because if // ACC_MODULE is set in the access flags, then NCDFE must be thrown, not CFE. classfile_parse_error("Unknown constant tag %u in class file %s", bad_constant, CHECK); }​ _access_flags.set_flags(flags);​ // This class and superclass _this_class_index = stream->get_u2_fast(); check_property( valid_cp_range(_this_class_index, cp_size) && cp->tag_at(_this_class_index).is_unresolved_klass(), "Invalid this class index %u in constant pool in class file %s", _this_class_index, CHECK);​ Symbol* const class_name_in_cp = cp->klass_name_at(_this_class_index); assert(class_name_in_cp != NULL, "class_name can't be null");​ // Update _class_name which could be null previously // to reflect the name in the constant pool _class_name = class_name_in_cp;​ // Don't need to check whether this class name is legal or not. // It has been checked when constant pool is parsed. // However, make sure it is not an array type. if (_need_verify) { guarantee_property(_class_name->byte_at(0) != JVM_SIGNATURE_ARRAY, "Bad class name in class file %s", CHECK); }​ // Checks if name in class file matches requested name if (_requested_name != NULL && _requested_name != _class_name) { ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_NoClassDefFoundError(), "%s (wrong name: %s)", _class_name->as_C_string(), _requested_name != NULL ? _requested_name->as_C_string() : "NoName" ); return; }​ // if this is an anonymous class fix up its name if it's in the unnamed // package. Otherwise, throw IAE if it is in a different package than // its host class. if (_host_klass != NULL) { fix_anonymous_class_name(CHECK); }​ // Verification prevents us from creating names with dots in them, this // asserts that that's the case. assert(is_internal_format(_class_name), "external class name format used internally");​ if (!is_internal()) { if (log_is_enabled(Debug, class, preorder)){ ResourceMark rm(THREAD); outputStream* log = Log(class, preorder)::debug_stream(); log->print("%s", _class_name->as_klass_external_name()); if (stream->source() != NULL) { log->print(" source: %s", stream->source()); } log->cr(); }​#if INCLUDE_CDS if (DumpLoadedClassList != NULL && stream->source() != NULL && classlist_file->is_open()) { // Only dump the classes that can be stored into CDS archive. // Anonymous classes such as generated LambdaForm classes are also not included. if (SystemDictionaryShared::is_sharing_possible(_loader_data) && _host_klass == NULL) { oop class_loader = _loader_data->class_loader(); ResourceMark rm(THREAD); // For the boot and platform class loaders, check if the class is not found in the // java runtime image. Additional check for the boot class loader is if the class // is not found in the boot loader's appended entries. This indicates that the class // is not useable during run time, such as the ones found in the --patch-module entries, // so it should not be included in the classlist file. if (((class_loader == NULL && !ClassLoader::contains_append_entry(stream->source())) || SystemDictionary::is_platform_class_loader(class_loader)) && !ClassLoader::is_jrt(stream->source())) { tty->print_cr("skip writing class %s from source %s to classlist file", _class_name->as_C_string(), stream->source()); } else { classlist_file->print_cr("%s", _class_name->as_C_string()); classlist_file->flush(); } } }#endif }​ // SUPERKLASS _super_class_index = stream->get_u2_fast(); _super_klass = parse_super_class(cp, _super_class_index, _need_verify, CHECK);​ // Interfaces _itfs_len = stream->get_u2_fast(); parse_interfaces(stream, _itfs_len, cp, &_has_nonstatic_concrete_methods, CHECK);​ assert(_local_interfaces != NULL, "invariant");​ // Fields (offsets are filled in later) _fac = new FieldAllocationCount(); parse_fields(stream, _access_flags.is_interface(), _fac, cp, cp_size, &_java_fields_count, CHECK);​ assert(_fields != NULL, "invariant");​ // Methods AccessFlags promoted_flags; parse_methods(stream, _access_flags.is_interface(), &promoted_flags, &_has_final_method, &_declares_nonstatic_concrete_methods, CHECK);​ assert(_methods != NULL, "invariant");​ // promote flags from parse_methods() to the klass' flags _access_flags.add_promoted_flags(promoted_flags.as_int());​ if (_declares_nonstatic_concrete_methods) { _has_nonstatic_concrete_methods = true; }​ // Additional attributes/annotations _parsed_annotations = new ClassAnnotationCollector(); parse_classfile_attributes(stream, cp, _parsed_annotations, CHECK);​ assert(_inner_classes != NULL, "invariant");​ // Finalize the Annotations metadata object, // now that all annotation arrays have been created. create_combined_annotations(CHECK);​ // Make sure this is the end of class file stream guarantee_property(stream->at_eos(), "Extra bytes at the end of class file %s", CHECK);​ // all bytes in stream read and parsed}

主要的过程是:

1、验证当前magic为0xCAFEBABE; 2、获取class文件的minor_version、major_version,并判断当前虚拟机是否支持该版本; 3、通过parse_constant_pool方法解析当前class的常量池; 4、解析当前class的access_flags; 5、解析当前class的父类; 6、解析当前class的接口;7、解析当前class的字段8、解析当前class的方法

解析字节码文件以后,需要对对应的语法进行检测,检测的主要逻辑在classFileParser.cpp中post_process_parsed_stream:

void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const stream, ConstantPool* cp, TRAPS) { assert(stream != NULL, "invariant"); assert(stream->at_eos(), "invariant"); assert(cp != NULL, "invariant"); assert(_loader_data != NULL, "invariant");​ if (_class_name == vmSymbols::java_lang_Object()) { check_property(_local_interfaces == Universe::the_empty_klass_array(), "java.lang.Object cannot implement an interface in class file %s", CHECK); } // We check super class after class file is parsed and format is checked if (_super_class_index > 0 && NULL ==_super_klass) { Symbol* const super_class_name = cp->klass_name_at(_super_class_index); if (_access_flags.is_interface()) { // Before attempting to resolve the superclass, check for class format // errors not checked yet. guarantee_property(super_class_name == vmSymbols::java_lang_Object(), "Interfaces must have java.lang.Object as superclass in class file %s", CHECK); } _super_klass = (const InstanceKlass*) SystemDictionary::resolve_super_or_fail(_class_name, super_class_name, _loader_data->class_loader(), _protection_domain, true, CHECK); }​ if (_super_klass != NULL) { if (_super_klass->has_nonstatic_concrete_methods()) { _has_nonstatic_concrete_methods = true; }​ if (_super_klass->is_interface()) { ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_IncompatibleClassChangeError(), "class %s has interface %s as super class", _class_name->as_klass_external_name(), _super_klass->external_name() ); return; } // Make sure super class is not final if (_super_klass->is_final()) { THROW_MSG(vmSymbols::java_lang_VerifyError(), "Cannot inherit from final class"); } }​ // Compute the transitive list of all unique interfaces implemented by this class _transitive_interfaces = compute_transitive_interfaces(_super_klass, _local_interfaces, _loader_data, CHECK);​ assert(_transitive_interfaces != NULL, "invariant");​ // sort methods _method_ordering = sort_methods(_methods);​ _all_mirandas = new GrowableArray<Method*>(20);​ klassVtable::compute_vtable_size_and_num_mirandas(&_vtable_size, &_num_miranda_methods, _all_mirandas, _super_klass, _methods, _access_flags, _major_version, _loader_data->class_loader(), _class_name, _local_interfaces, CHECK);​ // Size of Java itable (in words) _itable_size = _access_flags.is_interface() ? 0 : klassItable::compute_itable_size(_transitive_interfaces);​ assert(_fac != NULL, "invariant"); assert(_parsed_annotations != NULL, "invariant");​ _field_info = new FieldLayoutInfo(); layout_fields(cp, _fac, _parsed_annotations, _field_info, CHECK);​ // Compute reference typ _rt = (NULL ==_super_klass) ? REF_NONE : _super_klass->reference_type();​}

字节码文件解析之后,开始检查当前类对应的父类是否解析,是否允许被继承等。

解析完字节码文件后,开始创建对应的InstanceKlass 具体的如下:

InstanceKlass* ClassFileParser::create_instance_klass(bool changed_by_loadhook, TRAPS) { if (_klass != NULL) { return _klass; }​ InstanceKlass* const ik = InstanceKlass::allocate_instance_klass(*this, CHECK_NULL);​ fill_instance_klass(ik, changed_by_loadhook, CHECK_NULL);​ assert(_klass == ik, "invariant");​ ik->set_has_passed_fingerprint_check(false); if (UseAOT && ik->supers_have_passed_fingerprint_checks()) { uint64_t aot_fp = AOTLoader::get_saved_fingerprint(ik); if (aot_fp != 0 && aot_fp == _stream->compute_fingerprint()) { // This class matches with a class saved in an AOT library ik->set_has_passed_fingerprint_check(true); } else { ResourceMark rm; log_info(class, fingerprint)("%s : expected = " PTR64_FORMAT " actual = " PTR64_FORMAT, ik->external_name(), aot_fp, _stream->compute_fingerprint()); } }​ return ik;}

具体的构造klass对象的过程如下

InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& parser, TRAPS) { const int size = InstanceKlass::size(parser.vtable_size(), parser.itable_size(), nonstatic_oop_map_size(parser.total_oop_map_count()), parser.is_interface(), parser.is_anonymous(), should_store_fingerprint());​ const Symbol* const class_name = parser.class_name(); assert(class_name != NULL, "invariant"); ClassLoaderData* loader_data = parser.loader_data(); assert(loader_data != NULL, "invariant");​ InstanceKlass* ik;​ // Allocation if (REF_NONE == parser.reference_type()) { if (class_name == vmSymbols::java_lang_Class()) { // mirror ik = new (loader_data, size, THREAD) InstanceMirrorKlass(parser); } else if (is_class_loader(class_name, parser)) { // class loader ik = new (loader_data, size, THREAD) InstanceClassLoaderKlass(parser); } else { // normal ik = new (loader_data, size, THREAD) InstanceKlass(parser, InstanceKlass::_misc_kind_other); } } else { // reference ik = new (loader_data, size, THREAD) InstanceRefKlass(parser); }​ // Check for pending exception before adding to the loader data and incrementing // class count. Can get OOM here. if (HAS_PENDING_EXCEPTION) { return NULL; }​ assert(ik != NULL, "invariant");​ const bool publicize = !parser.is_internal();​ // Add all classes to our internal class loader list here, // including classes in the bootstrap (NULL) class loader. loader_data->add_class(ik, publicize); Atomic::inc(&_total_instanceKlass_count);​ return ik;}

根据接到的类型来构造对应的InstanceKlass对象。通过头部引入的类文件可以找到对应的InstanceKlass类文件。地址:

/src/share/vm/oops/instanceKlass.hpp

具体的为

class InstanceKlass: public Klass { friend class VMStructs; friend class JVMCIVMStructs; friend class ClassFileParser; friend class CompileReplay;​ protected: InstanceKlass(const ClassFileParser& parser, unsigned kind);​ public: InstanceKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }​ // See "The Java Virtual Machine Specification" section 2.16.2-5 for a detailed description // of the class loading & initialization procedure, and the use of the states. enum ClassState { allocated, // allocated (but not yet linked) loaded, // loaded and inserted in class hierarchy (but not linked yet) linked, // successfully linked/verified (but not initialized yet) being_initialized, // currently running class initializer fully_initialized, // initialized (successfull final state) initialization_error // error happened during initialization };​ static int number_of_instance_classes() { return _total_instanceKlass_count; }​ private: static volatile int _total_instanceKlass_count; static InstanceKlass* allocate_instance_klass(const ClassFileParser& parser, TRAPS);​ protected: // Annotations for this class Annotations* _annotations; // Package this class is defined in PackageEntry* _package_entry; // Array classes holding elements of this class. Klass* volatile _array_klasses; // Constant pool for this class. ConstantPool* _constants; // The InnerClasses attribute and EnclosingMethod attribute. The // _inner_classes is an array of shorts. If the class has InnerClasses // attribute, then the _inner_classes array begins with 4-tuples of shorts // [inner_class_info_index, outer_class_info_index, // inner_name_index, inner_class_access_flags] for the InnerClasses // attribute. If the EnclosingMethod attribute exists, it occupies the // last two shorts [class_index, method_index] of the array. If only // the InnerClasses attribute exists, the _inner_classes array length is // number_of_inner_classes * 4. If the class has both InnerClasses // and EnclosingMethod attributes the _inner_classes array length is // number_of_inner_classes * 4 + enclosing_method_attribute_size. Array<jushort>* _inner_classes;​ // the source debug extension for this klass, NULL if not specified. // Specified as UTF-8 string without terminating zero byte in the classfile, // it is stored in the instanceklass as a NULL-terminated UTF-8 string const char* _source_debug_extension; // Array name derived from this class which needs unreferencing // if this class is unloaded. Symbol* _array_name;​ // Number of heapOopSize words used by non-static fields in this klass // (including inherited fields but after header_size()). int _nonstatic_field_size; int _static_field_size; // number words used by static fields (oop and non-oop) in this klass // Constant pool index to the utf8 entry of the Generic signature, // or 0 if none. u2 _generic_signature_index; // Constant pool index to the utf8 entry for the name of source file // containing this klass, 0 if not specified. u2 _source_file_name_index; u2 _static_oop_field_count;// number of static oop fields in this klass u2 _java_fields_count; // The number of declared Java fields int _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks​ int _itable_len; // length of Java itable (in words) // _is_marked_dependent can be set concurrently, thus cannot be part of the // _misc_flags. bool _is_marked_dependent; // used for marking during flushing and deoptimization bool _is_being_redefined; // used for locking redefinition​ // The low two bits of _misc_flags contains the kind field. // This can be used to quickly discriminate among the four kinds of // InstanceKlass.​ static const unsigned _misc_kind_field_size = 2; static const unsigned _misc_kind_field_pos = 0; static const unsigned _misc_kind_field_mask = (1u << _misc_kind_field_size) - 1u;​ static const unsigned _misc_kind_other = 0; // concrete InstanceKlass static const unsigned _misc_kind_reference = 1; // InstanceRefKlass static const unsigned _misc_kind_class_loader = 2; // InstanceClassLoaderKlass static const unsigned _misc_kind_mirror = 3; // InstanceMirrorKlass​ // Start after _misc_kind field. enum { _misc_rewritten = 1 << 2, // methods rewritten. _misc_has_nonstatic_fields = 1 << 3, // for sizing with UseCompressedOops _misc_should_verify_class = 1 << 4, // allow caching of preverification _misc_is_anonymous = 1 << 5, // has embedded _host_klass field _misc_is_contended = 1 << 6, // marked with contended annotation _misc_has_nonstatic_concrete_methods = 1 << 7, // class/superclass/implemented interfaces has non-static, concrete methods _misc_declares_nonstatic_concrete_methods = 1 << 8, // directly declares non-static, concrete methods _misc_has_been_redefined = 1 << 9, // class has been redefined _misc_has_passed_fingerprint_check = 1 << 10, // when this class was loaded, the fingerprint computed from its // code source was found to be matching the value recorded by AOT. _misc_is_scratch_class = 1 << 11, // class is the redefined scratch class _misc_is_shared_boot_class = 1 << 12, // defining class loader is boot class loader _misc_is_shared_platform_class = 1 << 13, // defining class loader is platform class loader _misc_is_shared_app_class = 1 << 14 // defining class loader is app class loader }; u2 loader_type_bits() { return _misc_is_shared_boot_class|_misc_is_shared_platform_class|_misc_is_shared_app_class; } u2 _misc_flags; u2 _minor_version; // minor version number of class file u2 _major_version; // major version number of class file Thread* _init_thread; // Pointer to current thread doing initialization (to handle recusive initialization) OopMapCache* volatile _oop_map_cache; // OopMapCache for all methods in the klass (allocated lazily) MemberNameTable* _member_names; // Member names JNIid* _jni_ids; // First JNI identifier for static fields in this class jmethodID* volatile _methods_jmethod_ids; // jmethodIDs corresponding to method_idnum, or NULL if none intptr_t _dep_context; // packed DependencyContext structure nmethod* _osr_nmethods_head; // Head of list of on-stack replacement nmethods for this class#if INCLUDE_JVMTI BreakpointInfo* _breakpoints; // bpt lists, managed by Method* // Linked instanceKlasses of previous versions InstanceKlass* _previous_versions; // JVMTI fields can be moved to their own structure - see 6315920 // JVMTI: cached class file, before retransformable agent modified it in CFLH JvmtiCachedClassFileData* _cached_class_file;#endif​ volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change​ // Class states are defined as ClassState (see above). // Place the _init_state here to utilize the unused 2-byte after // _idnum_allocated_count. u1 _init_state; // state of class u1 _reference_type; // reference type​#if INCLUDE_JVMTI JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration#endif​ NOT_PRODUCT(int _verify_count;) // to avoid redundant verifies​ // Method array. Array<Method*>* _methods; // Default Method Array, concrete methods inherited from interfaces Array<Method*>* _default_methods; // Interface (Klass*s) this class declares locally to implement. Array<Klass*>* _local_interfaces; // Interface (Klass*s) this class implements transitively. Array<Klass*>* _transitive_interfaces; // Int array containing the original order of method in the class file (for JVMTI). Array<int>* _method_ordering; // Int array containing the vtable_indices for default_methods // offset matches _default_methods offset Array<int>* _default_vtable_indices;​ // Instance and static variable information, starts with 6-tuples of shorts // [access, name index, sig index, initval index, low_offset, high_offset] // for all fields, followed by the generic signature data at the end of // the array. Only fields with generic signature attributes have the generic // signature data set in the array. The fields array looks like following: // // f1: [access, name index, sig index, initial value index, low_offset, high_offset] // f2: [access, name index, sig index, initial value index, low_offset, high_offset] // ... // fn: [access, name index, sig index, initial value index, low_offset, high_offset] // [generic signature index] // [generic signature index] // ... Array<u2>* _fields;​ // embedded Java vtable follows here // embedded Java itables follows here // embedded static fields follows here // embedded nonstatic oop-map blocks follows here // embedded implementor of this interface follows here // The embedded implementor only exists if the current klass is an // iterface. The possible values of the implementor fall into following // three cases: // NULL: no implementor. // A Klass* that's not itself: one implementor. // Itself: more than one implementors. // embedded host klass follows here // The embedded host klass only exists in an anonymous class for // dynamic language support (JSR 292 enabled). The host class grants // its access privileges to this class also. The host class is either // named, or a previously loaded anonymous class. A non-anonymous class // or an anonymous class loaded through normal classloading does not // have this embedded field. //​ friend class SystemDictionary;  ......}

整体的过程通过命令行获取到需要加载的jar包,扫描所有的字节码文件检测是否符合规范。并根据字节码文件构造Klass类对象。包装类中的方法,构造函数,属性等信息。

下面是类初始化过程。也就是new一个对象时整个过程

截图中可以看到实例化过程中使用的是Klass对象。可以看出Klass和Class是相关的。同时Klass是全局唯一的。实例化对象的步骤如下:

1 找到Klass实例对象2 检测是否实例化的是抽象类3 检测Klass是否已经实例化4 分配空间内容

实例化的代码为(/scr/share/vm/interpreter/interpreterRunntime.cpp):

IRT_ENTRY(void, InterpreterRuntime::_new(JavaThread* thread, ConstantPool* pool, int index)) Klass* k_oop = pool->klass_at(index, CHECK); instanceKlassHandle klass (THREAD, k_oop);​ // Make sure we are not instantiating an abstract klass klass->check_valid_for_instantiation(true, CHECK);​ // Make sure klass is initialized klass->initialize(CHECK);​ // At this point the class may not be fully initialized // because of recursive initialization. If it is fully // initialized & has_finalized is not set, we rewrite // it into its fast version (Note: no locking is needed // here since this is an atomic byte write and can be // done more than once). // // Note: In case of classes with has_finalized we don't // rewrite since that saves us an extra check in // the fast version which then would call the // slow version anyway (and do a call back into // Java). // If we have a breakpoint, then we don't rewrite // because the _breakpoint bytecode would be lost. oop obj = klass->allocate_instance(CHECK); thread->set_vm_result(obj);IRT_END

具体实例化和分配空间(/src/share/vm/oops/instanceKlass.cpp):

instanceOop InstanceKlass::allocate_instance(TRAPS) { bool has_finalizer_flag = has_finalizer(); // Query before possible GC int size = size_helper(); // Query before forming handle.​ KlassHandle h_k(THREAD, this);​ instanceOop i;​ i = (instanceOop)CollectedHeap::obj_allocate(h_k, size, CHECK_NULL); if (has_finalizer_flag && !RegisterFinalizersAtInit) { i = register_finalizer(i, CHECK_NULL); } return i;}

标签: #was查看jvm使用情况 #mac编写脚本运行jar包