动态代理类生成从JDK到Hotspot

  本来想着从头开始写JVM但是之前写了动态代理设计模式,而动态代理模式中又涉及到动态生成Class对象的过程,索性就先了解一下对象生成过程,在后续学习过程如果发现写的有问题在纠正和补充!

一、动态代理类生成主流程

1、类加载、代理类实现接口Class对象集合获取

2、校验是否为为接口(java是单继承而动态生成的代理李继承了Proxy所以其他的只能是接口)

3、判断接口是不是public的,如果不是public则要判断是否为同一个目录下的,如果不是同一目录下的则生成代理类结束

4、生成代理类包名、类名组装

5、按照代理类实现接口Class对象动态生成字节码文件

6、调用native 方法对动态生成的字节码文件进行验证、魔数、版本号

7、字节码文件进行解析

8、根据ClassLoader 创建Klass对象,Klass对象对应java中的Class对象

9、解析信息回填到Klass对象

10、Klass对象内存空间分配并初始化static变量(这里的初始化不是指方法的执行)

11、返回Class对象

二、以主流程为主要架构,跟进查看具体实现和部分细节实现

1、类加载器、代理类实现接口Class对象集合

2、校验是否为为接口(java是单继承而动态生成的代理李继承了Proxy所以其他的只能是接口)

3、判断接口是不是public的,如果不是public则要判断是否为同一个目录下的,如果不是同一目录下的则生成代理类结束

4、代理类包名获取

proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";

public static final String PROXY_PACKAGE = "com.sun.proxy";

5、生成代理类类名

/*

* Choose a name for the proxy class to generate.

*/

long num = nextUniqueNumber.getAndIncrement();

String proxyName = proxyPkg + proxyClassNamePrefix + num;

// prefix for all proxy class names

private static final String proxyClassNamePrefix = "$Proxy”;

这就是我们看到的生成代理类类名称 com.sun.proxy.$Pxoy0、com.sun.proxy.$Pxoy1

6、获取代理类字节码字节流(.class 文件)

byte[] proxyClassFile = ProxyGenerator.generateProxyClass(

    proxyName, interfaces, accessFlags);

(1)、调用ProxyGenerator.generateProxyClass方法,参数类名、接口数组、访问权限

ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);

final byte[] var4 = var3.generateClassFile();

(2)、获取字节码文件generateClassFile()方法

  看方法名称就明白,是用来获取.class 文件字节码的,那就是要组装一个满足.class 文件格式的字节流

(3)、addProxyMethod 组装代理类方法

((List)var8).add(new ProxyGenerator.ProxyMethod(var3, var4, var5, var6, var2, null));

创建一个标识方法的对象ProxyMethod

(4)、方法元数据描述对象ProxyMethod 的成员变量

private class ProxyMethod {

    public String methodName;

    public Class[] parameterTypes;

    public Class returnType;

    public Class[] exceptionTypes;

    public Class fromClass;

    public String methodFieldName;

看到这些变量是不是很熟悉,方法名、方法参数类型、方法返回值类型、异常类型、方法所属类、方法属性名称即动态生成的代理类中Method类的变量名。

看构造函数中的变量名称;

动态代理类生成从JDK到Hotspot_第1张图片

(5)、添加完默认的equals、hashCode、toString方法之后遍历接口,获取接口所有方法并添加到

proxyMethods 集合;这个对象组装的有点像常量池中的符号引用。

(6)、生成 MethodInfo 对象,这里看看添加构造函数

private ProxyGenerator.MethodInfo generateConstructor() throws IOException {

    ProxyGenerator.MethodInfo var1 = new ProxyGenerator.MethodInfo("", "(Ljava/lang/reflect/InvocationHandler;)V", 1);

    DataOutputStream var2 = new DataOutputStream(var1.code);

    this.code_aload(0, var2);

    this.code_aload(1, var2);

    var2.writeByte(183);

    var2.writeShort(this.cp.getMethodRef("java/lang/reflect/Proxy", "", "(Ljava/lang/reflect/InvocationHandler;)V"));

    var2.writeByte(177);

    var1.maxStack = 10;

    var1.maxLocals = 2;

    var1.declaredExceptions = new short[0];

    return var1;

}

第一个参数 方法名称

第二个参数方法形参和方法返回值,构造函数形参 InvocationHandler  对象

第三个参数方法的访问权限

(7)、代理类中属性添加

while(var15.hasNext()) {

    ProxyGenerator.ProxyMethod var16 = (ProxyGenerator.ProxyMethod)var15.next();

    this.fields.add(new ProxyGenerator.FieldInfo(var16.methodFieldName, "Ljava/lang/reflect/Method;", 10));

    this.methods.add(var16.generateMethod());

}

(8)、动态组装的字节码文件输出到字节流

ByteArrayOutputStream var13 = new ByteArrayOutputStream();

DataOutputStream var14 = new DataOutputStream(var13);

动态代理类生成从JDK到Hotspot_第2张图片

代理类字节流动态生成。

OK 到这里JVM字节码文件生成了。下面看看按照字节码文件如何生成Class对象。

疑问:

上面的MethodInfo 动态代理类生成的方法信息描述,ProxyMethod 是动态代理类中Method 属性的描述?

加载字节码文件后Class对象生成过程

7、defineClass0调用native方法解析字节码文件生成Class对象

private static native Class defineClass0(ClassLoader loader, String name,

                                            byte[] b, int off, int len);

(1)、调用的是native方法,我们看jdk中的实现

目录: jdk/share/native/java/lang /classLoader.c

调用的native方法 如下

JNIEXPORT jclass JNICALL

Java_java_lang_ClassLoader_defineClass0(JNIEnv *env,

                                        jobject loader,

                                        jstring name,

                                        jbyteArray data,

                                        jint offset,

                                        jint length,

                                        jobject pd)

{

    return Java_java_lang_ClassLoader_defineClass1(env, loader, name, data, offset,length, pd, NULL);

}

(2)、调用Java_java_lang_ClassLoader_defineClass1 方法

result = JVM_DefineClassWithSource(env, utfName, loader, body, length, pd, utfSource);

调用JVM_DefineClassWithSource 生成jclass 文件

(3)、JVM_DefineClassWithSource 方法

目录: /hotspot/src/share/vm/prims/jvm.cpp

JVM_ENTRY(jclass, JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source))

  JVMWrapper2("JVM_DefineClassWithSource %s", name);


  return jvm_define_class_common(env, name, loader, buf, len, pd, source, true, THREAD);

JVM_END

(4)、调用公共方法jvm_define_class_common

// common code for JVM_DefineClass() and JVM_DefineClassWithSource()

// and JVM_DefineClassWithSourceCond()

static jclass jvm_define_class_common(JNIEnv *env, const char *name,

                                      jobject loader, const jbyte *buf,

                                      jsize len, jobject pd, const char *source,

                                      jboolean verify, TRAPS) {

  if (source == NULL)  source = "__JVM_DefineClass__";

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

  JavaThread* jt = (JavaThread*) THREAD;

  // Since exceptions can be thrown, class initialization can take place

  // if name is NULL no check for class name in .class stream has to be made.

  TempNewSymbol class_name = NULL;

  if (name != NULL) {

    const int str_len = (int)strlen(name);

    if (str_len > Symbol::max_length()) {

      // It's impossible to create this class;  the name cannot fit

      // into the constant pool.

      THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name);

    }

    class_name = SymbolTable::new_symbol(name, str_len, CHECK_NULL);

  }



  ResourceMark rm(THREAD);

  ClassFileStream st((u1*) buf, len, (char *)source);

  Handle class_loader (THREAD, JNIHandles::resolve(loader));

  if (UsePerfData) {

    is_lock_held_by_thread(class_loader,

                           ClassLoader::sync_JVMDefineClassLockFreeCounter(),

                           THREAD);

  }

  Handle protection_domain (THREAD, JNIHandles::resolve(pd));

  Klass* k = SystemDictionary::resolve_from_stream(class_name, class_loader,

                                                     protection_domain, &st,

                                                     verify != 0,

                                                     CHECK_NULL);



  return (jclass) JNIHandles::make_local(env, k->java_mirror());

}

删除了部分代码,主要看生成Klass对象方法

(5)、Klass* SystemDictionary::resolve_from_stream() 方法

目录:hotspot/src/share/vm/classfile/systemDictionary.cpp

Klass* SystemDictionary::resolve_from_stream(Symbol* class_name,

                                             Handle class_loader,

                                             Handle protection_domain,

                                             ClassFileStream* st,

                                             bool verify,

                                             TRAPS)

方法参数: 类名称、类加载器、对象、字节码文件字节流

(6)、调用解析类解析方法对字节码文件进行解析、验证

instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name,

                                                             loader_data,

                                                             protection_domain,

                                                             parsed_name,

                                                             verify,

                                                             THREAD);

(7)、字节码文件解析类

目录: hotspot/src/share/vm/classfile/classFileParser.hpp

instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,

                                                    ClassLoaderData* loader_data,

                                                    Handle protection_domain,

                                                    KlassHandle host_klass,

                                                    GrowableArray* cp_patches,

                                                    TempNewSymbol& parsed_name,

                                                    bool verify,

                                                    TRAPS) {

这个方法中完成了链接操作即验证、解析、准备阶段;整个解析流程比较长,看一下解析的流程如下;

// 字节码文件解析

instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,

                                                    ClassLoaderData* loader_data,

                                                    Handle protection_domain,

                                                    KlassHandle host_klass,

                                                    GrowableArray* cp_patches,

                                                    TempNewSymbol& parsed_name,

                                                    bool verify,

                                                    TRAPS) {



  // When a retransformable agent is attached, JVMTI caches the

  // class bytes that existed before the first retransformation.

  // If RedefineClasses() was used before the retransformable

  // agent attached, then the cached class bytes may not be the

  // original class bytes.

  JvmtiCachedClassFileData *cached_class_file = NULL;

  Handle class_loader(THREAD, loader_data->class_loader());

  bool has_default_methods = false;

  ResourceMark rm(THREAD);


  ClassFileStream* cfs = stream();

  // Timing

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

  JavaThread* jt = (JavaThread*) THREAD;

  PerfClassTraceTime ctimer(ClassLoader::perf_class_parse_time(),

                            ClassLoader::perf_class_parse_selftime(),

                            NULL,

                            jt->get_thread_stat()->perf_recursion_counts_addr(),

                            jt->get_thread_stat()->perf_timers_addr(),

                            PerfClassTraceTime::PARSE_CLASS);



  init_parsed_class_attributes(loader_data);

  if (JvmtiExport::should_post_class_file_load_hook()) {

    // Get the cached class file bytes (if any) from the class that

    // is being redefined or retransformed. We use jvmti_thread_state()

    // instead of JvmtiThreadState::state_for(jt) so we don't allocate

    // a JvmtiThreadState any earlier than necessary. This will help

    // avoid the bug described by 7126851.

    JvmtiThreadState *state = jt->jvmti_thread_state();

    if (state != NULL) {

      KlassHandle *h_class_being_redefined =

                     state->get_class_being_redefined();

      if (h_class_being_redefined != NULL) {

        instanceKlassHandle ikh_class_being_redefined =

          instanceKlassHandle(THREAD, (*h_class_being_redefined)());

          //之前缓存数据获取

        cached_class_file = ikh_class_being_redefined->get_cached_class_file();

      }

    }



    unsigned char* ptr = cfs->buffer();

    unsigned char* end_ptr = cfs->buffer() + cfs->length();

    JvmtiExport::post_class_file_load_hook(name, class_loader(), protection_domain,

                                           &ptr, &end_ptr, &cached_class_file);



    if (ptr != cfs->buffer()) {

      // JVMTI agent has modified class file data.

      // Set new class file stream using JVMTI agent modified

      // class file data.

      cfs = new ClassFileStream(ptr, end_ptr - ptr, cfs->source());

      set_stream(cfs);

    }

  }


  _host_klass = host_klass;

  _cp_patches = cp_patches;

  instanceKlassHandle nullHandle;

  // Figure out whether we can skip format checking (matching classic VM behavior)

  _need_verify = Verifier::should_verify_for(class_loader(), verify);

  // Set the verify flag in stream

  cfs->set_verify(_need_verify);

  // Save the class file name for easier error message printing.

  // 保存类文件名,以便打印错误信息

  _class_name = (name != NULL) ? name : vmSymbols::unknown_class_name();

  cfs->guarantee_more(8, CHECK_(nullHandle));  // magic, major, minor

  // Magic value

  // .class 文件开头魔数获取

  u4 magic = cfs->get_u4_fast();

  guarantee_property(magic == JAVA_CLASSFILE_MAGIC,

                     "Incompatible magic value %u in class file %s",

                     magic, CHECK_(nullHandle));

  // Version numbers

  // jdk版本号获取

  u2 minor_version = cfs->get_u2_fast();

  u2 major_version = cfs->get_u2_fast();

  // Check version numbers - we check this even with verifier off

  // 校验当前jvm是否支持该版本、不支持则抛出异常提示信息当前major、minor版本不支持

  if (!is_supported_version(major_version, minor_version)) {

    if (name == NULL) {

      Exceptions::fthrow(

        THREAD_AND_LOCATION,

        vmSymbols::java_lang_UnsupportedClassVersionError(),

        "Unsupported major.minor version %u.%u",

        major_version,

        minor_version);

    } else {

      ResourceMark rm(THREAD);

      Exceptions::fthrow(

        THREAD_AND_LOCATION,

        vmSymbols::java_lang_UnsupportedClassVersionError(),

        "%s : Unsupported major.minor version %u.%u",

        name->as_C_string(),

        major_version,

        minor_version);

    }

    return nullHandle;

  }


  _major_version = major_version;

  _minor_version = minor_version;


  // Check if verification needs to be relaxed for this class file

  // Do not restrict it to jdk1.0 or jdk1.1 to maintain backward compatibility (4982376)

  _relax_verify = Verifier::relax_verify_for(class_loader());


  // Constant pool

  // 常量池解析

  constantPoolHandle cp = parse_constant_pool(CHECK_(nullHandle));

  // 常量池长度

  int cp_size = cp->length();

  // cfs= class file  strem  

  cfs->guarantee_more(8, CHECK_(nullHandle));  // flags, this_class, super_class, infs_len

  // Access flags

  AccessFlags access_flags;

  jint flags = cfs->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_(nullHandle));

  access_flags.set_flags(flags);


  // This class and superclass

  // 本类、父类重常量池获取符号引用(应该没记错)

  u2 this_class_index = cfs->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_(nullHandle));


  Symbol*  class_name  = cp->unresolved_klass_at(this_class_index);

  assert(class_name != NULL, "class_name can't be null");


  // It's important to set parsed_name *before* resolving the super class.

  // (it's used for cleanup by the caller if parsing fails)

  parsed_name = class_name;

  // parsed_name is returned and can be used if there's an error, so add to

  // its reference count.  Caller will decrement the refcount.

  parsed_name->increment_refcount();


  // Update _class_name which could be null previously to be class_name

  _class_name = class_name;


  // 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_(nullHandle));

  }



  Klass* preserve_this_klass;   // for storing result across HandleMark

  // release all handles when parsing is done

  { HandleMark hm(THREAD);

    // Checks if name in class file matches requested name

    if (name != NULL && class_name != name) {

      ResourceMark rm(THREAD);

      Exceptions::fthrow(

        THREAD_AND_LOCATION,

        vmSymbols::java_lang_NoClassDefFoundError(),

        "%s (wrong name: %s)",

        name->as_C_string(),

        class_name->as_C_string()

      );

      return nullHandle;

    }


    if (TraceClassLoadingPreorder) {

      tty->print("[Loading %s", (name != NULL) ? name->as_klass_external_name() : "NoName");

      if (cfs->source() != NULL) tty->print(" from %s", cfs->source());

      tty->print_cr("]");

    }


    u2 super_class_index = cfs->get_u2_fast();

    instanceKlassHandle super_klass = parse_super_class(super_class_index,

                                                        CHECK_NULL);


    // Interfaces

    u2 itfs_len = cfs->get_u2_fast();

    // 接口解析

    Array* local_interfaces =

      parse_interfaces(itfs_len, protection_domain, _class_name,

                       &has_default_methods, CHECK_(nullHandle));


    u2 java_fields_count = 0;

    // Fields (offsets are filled in later)

    FieldAllocationCount fac;

    Array* fields = parse_fields(class_name,

                                     access_flags.is_interface(),

                                     &fac, &java_fields_count,

                                     CHECK_(nullHandle));

    // Methods

    // 方法解析

    bool has_final_method = false;

    AccessFlags promoted_flags;

    promoted_flags.set_flags(0);

    Array* methods = parse_methods(access_flags.is_interface(),

                                            &promoted_flags,

                                            &has_final_method,

                                            &has_default_methods,

                                            CHECK_(nullHandle));



    // Additional attributes

    ClassAnnotationCollector parsed_annotations;

    parse_classfile_attributes(&parsed_annotations, CHECK_(nullHandle));


    // Make sure this is the end of class file stream

    guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle));


    // We check super class after class file is parsed and format is checked

    if (super_class_index > 0 && super_klass.is_null()) {

      Symbol*  sk  = 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(sk == vmSymbols::java_lang_Object(),

                           "Interfaces must have java.lang.Object as superclass in class file %s",

                           CHECK_(nullHandle));

      }

      Klass* k = SystemDictionary::resolve_super_or_fail(class_name, sk,

                                                         class_loader,

                                                         protection_domain,

                                                         true,

                                                         CHECK_(nullHandle));



      KlassHandle kh (THREAD, k);

      super_klass = instanceKlassHandle(THREAD, kh());

    }

    if (super_klass.not_null()) {

      if (super_klass->has_default_methods()) {

        has_default_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 nullHandle;

      }

      // Make sure super class is not final

      if (super_klass->is_final()) {

        THROW_MSG_(vmSymbols::java_lang_VerifyError(), "Cannot inherit from final class", nullHandle);

      }

    }


    // save super klass for error handling.

    _super_klass = super_klass;

    // Compute the transitive list of all unique interfaces implemented by this class

    _transitive_interfaces =

          compute_transitive_interfaces(super_klass, local_interfaces, CHECK_(nullHandle));

    // sort methods

    intArray* method_ordering = sort_methods(methods);

    // promote flags from parse_methods() to the klass' flags

    access_flags.add_promoted_flags(promoted_flags.as_int());


    // Size of Java vtable (in words)

    int vtable_size = 0;

    int itable_size = 0;

    int num_miranda_methods = 0;

    GrowableArray all_mirandas(20);

    klassVtable::compute_vtable_size_and_num_mirandas(

        &vtable_size, &num_miranda_methods, &all_mirandas, super_klass(), methods,

        access_flags, class_loader, class_name, local_interfaces,

                                                      CHECK_(nullHandle));

    // Size of Java itable (in words)

    itable_size = access_flags.is_interface() ? 0 : klassItable::compute_itable_size(_transitive_interfaces);

    FieldLayoutInfo info;

    layout_fields(class_loader, &fac, &parsed_annotations, &info, CHECK_NULL);

    int total_oop_map_size2 =

          InstanceKlass::nonstatic_oop_map_size(info.total_oop_map_count);

    // Compute reference type

    ReferenceType rt;

    if (super_klass() == NULL) {

      rt = REF_NONE;

    } else {

      rt = super_klass->reference_type();

    }

    // We can now create the basic Klass* for this klass

    // 根据ClassLoader 创建Klass对象

    _klass = InstanceKlass::allocate_instance_klass(loader_data,

                                                    vtable_size,

                                                    itable_size,

                                                    info.static_field_size,

                                                    total_oop_map_size2,

                                                    rt,

                                                    access_flags,

                                                    name,

                                                    super_klass(),

                                                    !host_klass.is_null(),

                                                    CHECK_(nullHandle));

    

    instanceKlassHandle this_klass (THREAD, _klass);

    assert(this_klass->static_field_size() == info.static_field_size, "sanity");

    assert(this_klass->nonstatic_oop_map_count() == info.total_oop_map_count,

           "sanity");

    // Fill in information already parsed

    // 填写已解析信息

    this_klass->set_should_verify_class(verify);

    jint lh = Klass::instance_layout_helper(info.instance_size, false);

    this_klass->set_layout_helper(lh);

    assert(this_klass->oop_is_instance(), "layout is correct");

    assert(this_klass->size_helper() == info.instance_size, "correct size_helper");

    // Not yet: supers are done below to support the new subtype-checking fields

    //this_klass->set_super(super_klass());

    this_klass->set_class_loader_data(loader_data);

    this_klass->set_nonstatic_field_size(info.nonstatic_field_size);

    this_klass->set_has_nonstatic_fields(info.has_nonstatic_fields);

    this_klass->set_static_oop_field_count(fac.count[STATIC_OOP]);

    apply_parsed_class_metadata(this_klass, java_fields_count, CHECK_NULL);

    if (has_final_method) {

      this_klass->set_has_final_method();

    }

    this_klass->copy_method_ordering(method_ordering, CHECK_NULL);

    // The InstanceKlass::_methods_jmethod_ids cache

    // is managed on the assumption that the initial cache

    // size is equal to the number of methods in the class. If

    // that changes, then InstanceKlass::idnum_can_increment()

    // has to be changed accordingly.

    this_klass->set_initial_method_idnum(methods->length());

    this_klass->set_name(cp->klass_name_at(this_class_index));

    if (is_anonymous())  // I am well known to myself

      cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve


    // 填写已解析版本号信息

    this_klass->set_minor_version(minor_version);

    this_klass->set_major_version(major_version);

    this_klass->set_has_default_methods(has_default_methods);


    // Set up Method*::intrinsic_id as soon as we know the names of methods.

    // (We used to do this lazily, but now we query it in Rewriter,

    // which is eagerly done for every method, so we might as well do it now,

    // when everything is fresh in memory.)

    if (Method::klass_id_for_intrinsics(this_klass()) != vmSymbols::NO_SID) {

      for (int j = 0; j < methods->length(); j++) {

        methods->at(j)->init_intrinsic_id();

      }

    }


    if (cached_class_file != NULL) {

      // JVMTI: we have an InstanceKlass now, tell it about the cached bytes

      // InstanceKlass 对象缓存

      this_klass->set_cached_class_file(cached_class_file);

    }


    // Fill in field values obtained by parse_classfile_attributes

    if (parsed_annotations.has_any_annotations())

      parsed_annotations.apply_to(this_klass);

    apply_parsed_class_attributes(this_klass);


    // Miranda methods

    if ((num_miranda_methods > 0) ||

        // if this class introduced new miranda methods or

        (super_klass.not_null() && (super_klass->has_miranda_methods()))

        // super class exists and this class inherited miranda methods

        ) {

      this_klass->set_has_miranda_methods(); // then set a flag

    }


    // Fill in information needed to compute superclasses.

    // 初始化super类的信息

    this_klass->initialize_supers(super_klass(), CHECK_(nullHandle));


    // Initialize itable offset tables

    klassItable::setup_itable_offset_table(this_klass);


    // Compute transitive closure of interfaces this class implements

    // Do final class setup

    fill_oop_maps(this_klass, info.nonstatic_oop_map_count, info.nonstatic_oop_offsets, info.nonstatic_oop_counts);


    // Fill in has_finalizer, has_vanilla_constructor, and layout_helper

    set_precomputed_flags(this_klass);


    // reinitialize modifiers, using the InnerClasses attribute

    int computed_modifiers = this_klass->compute_modifier_flags(CHECK_(nullHandle));

    this_klass->set_modifier_flags(computed_modifiers);


    // check if this class can access its super class

    check_super_class_access(this_klass, CHECK_(nullHandle));


    // check if this class can access its superinterfaces

    check_super_interface_access(this_klass, CHECK_(nullHandle));


    // check if this class overrides any final method

    check_final_method_override(this_klass, CHECK_(nullHandle));


    // check that if this class is an interface then it doesn't have static methods

    if (this_klass->is_interface()) {

      /* An interface in a JAVA 8 classfile can be static */

      if (_major_version < JAVA_8_VERSION) {

        check_illegal_static_method(this_klass, CHECK_(nullHandle));

      }

    }



    // Allocate mirror and initialize static fields

    //// 初始化分配的static字段

    // 1.必须加载Class对象实例(mirror),它用于分配空间

    // 2.创建java.lang.Class instance并分配空间

    // 3.建立 mirror(java.lang.Class instance)-》klass的关系(对应Metadata中的klass关系)

    // 4.判断是否是数组(普通数组/object数组)

    // 5.初始化mirror的field

    // 5.1 获取到该类的field,找到静态的变量,并初始化


    java_lang_Class::create_mirror(this_klass, protection_domain, CHECK_(nullHandle));


    // Generate any default methods - default methods are interface methods

    // that have a default implementation.  This is new with Lambda project.

    if (has_default_methods ) {

      DefaultMethods::generate_default_methods(

          this_klass(), &all_mirandas, CHECK_(nullHandle));

    }


    // Update the loader_data graph.

    //记录this_klass的类中依赖,以便后续进行GC

    record_defined_class_dependencies(this_klass, CHECK_NULL);

    ClassLoadingService::notify_class_loaded(InstanceKlass::cast(this_klass()),

                                             false /* not shared class */);

    if (TraceClassLoading) {

      ResourceMark rm;

      // print in a single call to reduce interleaving of output

      if (cfs->source() != NULL) {

        tty->print("[Loaded %s from %s]\n", this_klass->external_name(),

                   cfs->source());

      } else if (class_loader.is_null()) {

        if (THREAD->is_Java_thread()) {

          Klass* caller = ((JavaThread*)THREAD)->security_get_caller_class(1);

          tty->print("[Loaded %s by instance of %s]\n",

                     this_klass->external_name(),

                     InstanceKlass::cast(caller)->external_name());

        } else {

          tty->print("[Loaded %s]\n", this_klass->external_name());

        }

      } else {

        tty->print("[Loaded %s from %s]\n", this_klass->external_name(),

                   InstanceKlass::cast(class_loader->klass())->external_name());

      }

    }


    if (TraceClassResolution) {

      ResourceMark rm;

      // print out the superclass.

      const char * from = this_klass()->external_name();

      if (this_klass->java_super() != NULL) {

        tty->print("RESOLVE %s %s (super)\n", from, InstanceKlass::cast(this_klass->java_super())->external_name());

      }

      // print out each of the interface classes referred to by this class.

      Array* local_interfaces = this_klass->local_interfaces();

      if (local_interfaces != NULL) {

        int length = local_interfaces->length();

        for (int i = 0; i < length; i++) {

          Klass* k = local_interfaces->at(i);

          InstanceKlass* to_class = InstanceKlass::cast(k);

          const char * to = to_class->external_name();

          tty->print("RESOLVE %s %s (interface)\n", from, to);

        }

      }

    }


    // preserve result across HandleMark

    preserve_this_klass = this_klass();

  }

  // Create new handle outside HandleMark (might be needed for

  // Extended Class Redefinition)

  instanceKlassHandle this_klass (THREAD, preserve_this_klass);

  debug_only(this_klass->verify();)

  // Clear class if no error has occurred so destructor doesn't deallocate it

  _klass = NULL;

  // 返回结果即Klass 对象

  return this_klass;

}

三、总结

1、动态代理类生成主要由两部分组即java代码实现动态字节码文件生成和c、c++部分实现的验证、解析字节码文件即.class 文件来生成Class对象。

2、平时使用时类对象的创建流程为:类加载、验证、解析、准备、初始化、对象创建、使用、卸载,这里动态生成时相当于省去了类加载这一步,因为是在程序运行时动态生成并且是在内存中。

3、oop-klass 模型在之后jvm学习过程中注意一下。

4、其中第一部分java实现的动态生成字节码文件的方式除了现在jdk提供的这种方式还有很多,比如性能比较高的AWS和使用比较方便的Javassist 框架来编写字节码文件。

下一篇文章中我们学习一下Javassist 字节码框架并看看dubbo中用它生成代理类的实现……

参考文章:

https://www.jianshu.com/p/b6cb4c694951

https://www.jianshu.com/p/b57a83ad8baa

https://blog.csdn.net/qq_31430665/article/details/106689164?%3E

https://www.cnblogs.com/porter/p/9399716.html

你可能感兴趣的:(jvm)