Hotspot 类文件加载、链接和初始化

在熟悉《class文件和字节码解析》和《Java对象内存表示机制》了之后,我们对类有了更进一步的认识,那么类文件是如何变成Hotspot中的Klass了?

加载器机制

 《类加载机制》一文件中,我们已知道java加载器双亲委派机制,也知道调用loadClass方法可自定义加载类。不管我们在JAVA中通过JNI的方式(ClassLoader JNI接口的实现源码在jdk/src/share/native/java/lang/ClassLoader.c中)或者在虚拟机中直接调用,最终关系都离不开以下几个类:
在这里插入图片描述
虚拟机自动加载以java.lang.String为例

加载器初始化
Threads::create_vm()《openJdk的启动流程》中的方法->
  init_globals()–>
  classLoader_init()–>
   ClassLoader::initialize()

加载
Threads::create_vm()->
  initialize_class(vmSymbols::java_lang_String(), CHECK_0)–>
  SystemDictionary::resolve_or_fail–>
  SystemDictionary::resolve_instance_class_or_null->
  SystemDictionary::load_instance_class->
   ClassLoader::load_classfile->
    ClassFileParser::parseClassFile

链接
Threads::create_vm()->
  initialize_class(vmSymbols::java_lang_String(), CHECK_0)–>
  InstanceKlass::initialize–>
  InstanceKlass::link_class->
  InstanceKlass::link_class_impl

ClassLoader JNI接口方式

加载
class.getClassLoader().loadClass (java中的方法)->
 classLoader.findBootstrapClass–>
  SystemDictionary::resolve_or_null–>
  SystemDictionary::resolve_instance_class_or_null->
  SystemDictionary::load_instance_class->
   ClassLoader::load_classfile->
    ClassFileParser::parseClassFile

链接
InterpretrRuntime:_new (java 中 new语法,触发)->
 InstanceKlass::initialize–>
 InstanceKlass::link_class->
 InstanceKlass::link_class_impl

ClassLoader

ClassLoader类的定义在classfile/classLoader.hpp中,ClassLoader是用于加载Java核心类文件。

#ClassLoader是一个静态类,里面全是全局的东档
class ClassLoader: AllStatic {
  //ClassPathEntry类指针,ClassPathEntry用于表示单个classpath路径,所有的ClassPathEntry实例以链表的形式关联起来,_first_entry表示链表的第一个实例
  static ClassPathEntry* _first_entry;
  // 表示链表的最后一个实例
  static ClassPathEntry* _last_entry;
  //ClassPathEntry实例以链表数量
  static int _num_entries;
  // 用于保存已经加载过的包名
  static PackageHashtable* _package_hash_table;
 
  //以下几个方法ClassPathEntry链表相关的操作方法:
  //setup_search_path
  //contains_entry
  //add_to_list
  //num_classpath_entrie,
  //classpath_entry
  //create_class_path_entry
  //update_class_path_entry_list  
  
  //加载zip文件读取写入等操作的动态链接库
  //load_zip_library 
 
  //创建虚拟机时的初始化的方法,其调用路径
  //Threads::create_vm()《openJdk的启动流程》中的方法->
  //init_globals()-->
  //classLoader_init()-->
  //ClassLoader::initialize()
  void ClassLoader::initialize() {
  	assert(_package_hash_table == NULL, "should have been initialized by now.");
  	EXCEPTION_MARK;
 
  	if (UsePerfData) {
    	//如果开始性能检测则初始化各计数器
    	NEWPERFTICKCOUNTER(_perf_accumulated_time, SUN_CLS, "time");
    	NEWPERFTICKCOUNTER(_perf_class_init_time, SUN_CLS, "classInitTime");
  	}
 
  	//加载读写zip文件的动态链接库
  	load_zip_library();
  	//设置加载核心jar包的搜索路径,从系统参数Arguments中获取
  	//使用参数-XX:+TraceClassPaths会打印出具体
  	//bootstrap路径
  	//classpath
  	//path
  	setup_bootstrap_search_path();
  	//如果是惰性启动加载,即启动时不加载rt.jar等文件
  	if (LazyBootClassLoader) {
    	//设置meta_index_path,设置完成后会触发对meta_index_path下文件的解析
    	setup_bootstrap_meta_index();
  	}
  }

  //根据类名加载指定类文件的方法
  instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) {
  	ResourceMark rm(THREAD);
  	//获取类名
  	const char* class_name = h_name->as_C_string();
  	//-XX:+TraceClassLoadingPreorder参数能打印出来
  	EventMark m("loading class %s", class_name);
  	ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion);
 
  	stringStream st;
  	st.print_raw(h_name->as_utf8());
  	st.print_raw(".class");
  	//获取文件名
  	const char* file_name = st.as_string();
  	ClassLoaderExt::Context context(class_name, file_name, THREAD);
 
  	//ClassFileStream表示Class文件的字节流
  	ClassFileStream* stream = NULL;
  	int classpath_index = 0;
  	ClassPathEntry* e = NULL;
  	instanceKlassHandle h;
  	{
   	 	//从第一个ClassPathEntry开始遍历所有的ClassPathEntry
    	e = _first_entry;
    	while (e != NULL) {
      		stream = e->open_stream(file_name, CHECK_NULL);
      		//如果检查返回false则返回null,check方法默认返回true
      		if (!context.check(stream, classpath_index)) {
        		return h; // NULL
      		}
      		//如果找到目标文件则跳出循环
      		if (stream != NULL) {
        		break;
      		}
      		e = e->next();
      		++classpath_index;
    	}
  	}
  	//如果找到了目标class文件
  	if (stream != NULL) {
    	//构建一个ClassFileParser实例
    	ClassFileParser parser(stream);
    	//构建一个ClassLoaderData实例
    	ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
    	Handle protection_domain;
    	TempNewSymbol parsed_name = NULL;
    	//解析并加载class文件,注意此时并未开始链接
    	//-XX:+TraceClassLoading可打出加载好的日志
    	instanceKlassHandle result = parser.parseClassFile(h_name,loader_data,protection_domain,parsed_name,context.should_verify(classpath_index),THREAD);
    	//如果解析异常
    	if (HAS_PENDING_EXCEPTION) {
      		ResourceMark rm;
      		if (DumpSharedSpaces) {
        		//打印异常
        		tty->print_cr("Preload Error: Failed to load %s", class_name);
      		}
      		return h;
    	}
    	//调用ClassLoader的add_package方法,把当前类的包名加入到_package_hash_table中
    	h = context.record_result(classpath_index, e, result, THREAD);
  	} else {
    	//没有找到目标文件
    	if (DumpSharedSpaces) {
      		tty->print_cr("Preload Warning: Cannot find %s", class_name);
    	}
  	}
  	return h;
}
Symbol

Symbol类的定义位于oops/symbol.hpp中,Symbol表示一个规范化的字符串形式的描述符,如方法Object m(int i, double d, Thread t) {…}对应的方法描述符就是(IDLjava/lang/Thread;)Ljava/lang/Object.关于描述述的概念在《class文件和字节码解析

//vmSymbols::java_lang_String()就是虚拟机提前创建好的java.lang.String的描述符
class Symbol : MetaspaceObj {
  volatile short _refcount;//表示该Symbol的引用计数
  unsigned short _length;//UTF-8字符串的长度     
  int  _identity_hash;//hash唯一标识码
  jbyte _body[1];//用于存储描述符对应的字符串

   //可以操作_body属性的
   //byte_at_put(int index, int value)

   //打印具体字符串内容
   //as_C_string(),as_utf8()
   
   //引用计数相关
   //refcount(),increment_refcount(),decrement_refcount() 
}
SymbolTable

SymbolTable的定义位于classfile/symbolTable.hpp中,对应于C/C++编译过程的符号表,用于保存管理所有的Symbol实例,StringTable就是Java特有的字符串常量池.用作快速查找字符串

SystemDictionary

SystemDictionary类的定义在classfile/systemDictionary.hpp中,是一个系统字典类,用于保存所有已经加载完成的类。

//SystemDictionary相当于类加载的一个统一入口,同时提供查找已加载的类和加载新的类的服务
class SystemDictionary : AllStatic {
 
  //JVM对不同数据设置不同的hashMap容量,保存在_primelist中,当前hashMap要多大的容量取决于_sdgeneration的值
  static int  _sdgeneration;
  static const int  _primelist[_prime_array_size];

  //实际保存已加载类的HashMap
  //key使用类名加classloader的形式
  //dictionary()->compute_hash(name_h, loader_data);
  static Dictionary*            _dictionary;

  //当类加载的过程中临时存储键值对的地方,底层数据结构同Dictionary类
  static PlaceholderTable*       _placeholders;

  //JVM 将类信息加载, 解析成为元数据,并根据是否需要修改,将其分类为 Read-Only 部分和 Read-Write 部分。然后,将这些元数据直接存储在文件系统中,作为所谓的 Shared Archive.
  // 共享架构下用于保存已加载类的HashMap
  static Dictionary*             _shared_dictionary;

  // 发生修改的次数,类加载或者删除都会增加该计数器
  static int                     _number_of_modifications;

  // 系统类加载器的对象锁
  static oop                     _system_loader_lock_obj;

  // 保存类加载器加载约束的HashTable
  static LoaderConstraintTable*  _loader_constraints;

  // 保存类解析错误的HashTable
  static ResolutionErrorTable*   _resolution_errors;

  // Invoke methods (JSR 292)
  //保存MethodHandle调用的解析结果
  static SymbolPropertyTable*    _invoke_method_table;

  //系统类加载器的引用
  static oop  _java_system_loader;

  //属性操作的相关方法
  //check_constraints,add_placeholder,add_klass,dictionary

  //根据类加载器和类名加载类的方法
  //resolve_or_fail,resolve_or_null,resolve_super_or_fail
  
  //根据class文件流,类加载器和类名加载类的方法
  //parse_stream,resolve_from_stream
  
  //解析类的最终都会进入此方法
  instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
	  instanceKlassHandle nh = instanceKlassHandle(); // null Handle
	  //如果class_loader为空,即Java类加载器无法加载该类了
	  if (class_loader.is_null()) {
	    instanceKlassHandle k;
	    //目标类未加载
	    if (k.is_null()) {
	      //执行目标类的加载
	      k = ClassLoader::load_classfile(class_name, CHECK_(nh));
	    }
	 
	    //如果已经加载则查找加载的类
	    //并把其加入到_dictionary中
	    if (!k.is_null()) {
	      k = find_or_define_instance_class(class_name, class_loader, k, CHECK_(nh));
	    }
	    return k;
	  } else {
	    ResourceMark rm(THREAD);
	 
	    assert(THREAD->is_Java_thread(), "must be a JavaThread");
	    JavaThread* jt = (JavaThread*) THREAD;
	    
	    //构建JNI调用的参数,即类名
	    Handle s = java_lang_String::create_from_symbol(class_name, CHECK_(nh));
	    Handle string = java_lang_String::externalize_classname(s, CHECK_(nh));
	    //调用的结果
	    JavaValue result(T_OBJECT);
	    //结果的处理器
	    KlassHandle spec_klass (THREAD, SystemDictionary::ClassLoader_klass());
	    //调用Java的类加载器加载特定类
	    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));
	    }
	    //从加载结果中获取目标类oop
	    assert(result.get_type() == T_OBJECT, "just checking");
	    oop obj = (oop) result.get_jobject();
	 
	    //检查访问权限
	    if ((obj != NULL) && !(java_lang_Class::is_primitive(obj))) {
	      instanceKlassHandle k =
	                instanceKlassHandle(THREAD, java_lang_Class::as_Klass(obj));
	      //检查类名是否一致
	      if (class_name == k->name()) {
	        return k;
	      }
	    }
	    //类加载失败,返回空对象
	    return nh;
	  }
	}
}
ClassFileParser&Verifier

ClassFileParser类的定义在classfile/classFileParser.hpp中,类解析器,用来解析class文件,它利用ClassFileStream读取class文件的输入流作为ClassFileParser.parseClassFile核心方法的输入。

Veritier类的定义在classfile/Veritier.hpp中,类验证器。其核心方法是Verifier::verify

InstanceKlass

做为oop-klass二分模型的主要类,不在做详细介绍

InstanceKlass{

	void initialize_impl(instanceKlassHandle this_oop, TRAPS) {
	  //完成此类的链接,如果已链接则会立即返回
	  this_oop->link_class(CHECK);
	 
	  DTRACE_CLASSINIT_PROBE(required, InstanceKlass::cast(this_oop()), -1);
	 
	  bool wait = false;
	 
	  // Step 1
	  {
	    //获取对象锁
	    oop init_lock = this_oop->init_lock();
	    ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
	 
	    Thread *self = THREAD; // it's passed the current thread
	 
	    // Step 2
	    //如果正在初始化则等待初始化完成
	    while(this_oop->is_being_initialized() && !this_oop->is_reentrant_initialization(self)) {
	        wait = true;
	      ol.waitUninterruptibly(CHECK);
	    }
	 
	    //等待超时返回
	    if (this_oop->is_being_initialized() && this_oop->is_reentrant_initialization(self)) {
	      DTRACE_CLASSINIT_PROBE_WAIT(recursive, InstanceKlass::cast(this_oop()), -1,wait);
	      return;
	    }
	 
	    //初始化完成返回
	    if (this_oop->is_initialized()) {
	      DTRACE_CLASSINIT_PROBE_WAIT(concurrent, InstanceKlass::cast(this_oop()), -1,wait);
	      return;
	    }
	 
	    //状态异常,抛出异常
	    if (this_oop->is_in_error_state()) {
	      DTRACE_CLASSINIT_PROBE_WAIT(erroneous, InstanceKlass::cast(this_oop()), -1,wait);
	      ResourceMark rm(THREAD);
	      const char* desc = "Could not initialize class ";
	      const char* className = this_oop->external_name();
	      size_t msglen = strlen(desc) + strlen(className) + 1;
	      char* message = NEW_RESOURCE_ARRAY(char, msglen);
	      if (NULL == message) {
	        // Out of memory: can't create detailed error message
	        THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), className);
	      } else {
	        jio_snprintf(message, msglen, "%s%s", desc, className);
	        THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), message);
	      }
	    }
	 
	    // 设置状态,初始化进行中
	    this_oop->set_init_state(being_initialized);
	    this_oop->set_init_thread(self);
	  }
	 
	  // Step 7
	  //如果不是一个接口而是一个类则需要初始化它的父类
	  if (!this_oop->is_interface()) {
	     //获取父类
	    Klass* super_klass = this_oop->super();
	    //初始化父类
	    if (super_klass != NULL && super_klass->should_be_initialized()) {
	      super_klass->initialize(THREAD);
	    }
	    //实现的接口存在默认方法则初始化接口
	    if (!HAS_PENDING_EXCEPTION && this_oop->has_default_methods()) {
	      this_oop->initialize_super_interfaces(this_oop, THREAD);
	    }
	 
	    //初始化异常,抛出异常
	    if (HAS_PENDING_EXCEPTION) {
	      Handle e(THREAD, PENDING_EXCEPTION);
	      CLEAR_PENDING_EXCEPTION;
	      {
	        EXCEPTION_MARK;
	        this_oop->set_initialization_state_and_notify(initialization_error, THREAD);
	        CLEAR_PENDING_EXCEPTION;
	      }
	      DTRACE_CLASSINIT_PROBE_WAIT(super__failed, InstanceKlass::cast(this_oop()), -1,wait);
	      THROW_OOP(e());
	    }
	  }
	 
	  // Step 8
	  {
	    assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl");
	    JavaThread* jt = (JavaThread*)THREAD;
	    DTRACE_CLASSINIT_PROBE_WAIT(clinit, InstanceKlass::cast(this_oop()), -1,wait);
	    //执行静态方法
	    //final static变量和接口的其值为编译期常数的域首先初始化(在准备阶段执行)
	    //按文本顺序执,下面三种情况会会javac整理进<cinit>
	    //类变量的初始化器 static int b = 4;
	    //静态初始化函数 static {...}
	    //接口域初始化器 static int a = 4;
	    this_oop->call_class_initializer(THREAD);
	  }
	 
	  // Step 9
	  if (!HAS_PENDING_EXCEPTION) {
	    //设置状态初始化完成
	    this_oop->set_initialization_state_and_notify(fully_initialized, CHECK);
	    { ResourceMark rm(THREAD);
	      debug_only(this_oop->vtable()->verify(tty, true);)
	    }
	  }
	  else {
	    //初始化失败,抛出异常
	    Handle e(THREAD, PENDING_EXCEPTION);
	    CLEAR_PENDING_EXCEPTION;
	    JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
	    {
	      EXCEPTION_MARK;
	      this_oop->set_initialization_state_and_notify(initialization_error, THREAD);
	      CLEAR_PENDING_EXCEPTION;   // ignore any exception thrown, class initialization error is thrown below
	      JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
	    }
	    DTRACE_CLASSINIT_PROBE_WAIT(error, InstanceKlass::cast(this_oop()), -1,wait);
	    if (e->is_a(SystemDictionary::Error_klass())) {
	      THROW_OOP(e());
	    } else {
	      JavaCallArguments args(e);
	      THROW_ARG(vmSymbols::java_lang_ExceptionInInitializerError(),
	                vmSymbols::throwable_void_signature(),
	                &args);
	    }
	  }
	  DTRACE_CLASSINIT_PROBE_WAIT(end, InstanceKlass::cast(this_oop()), -1,wait);
	}

	bool link_class_impl(
	    instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS) {
	  //如果类状态错误,则抛出异常
	  if (this_oop->is_in_error_state()) {
	    ResourceMark rm(THREAD);
	    THROW_MSG_(vmSymbols::java_lang_NoClassDefFoundError(),
	               this_oop->external_name(), false);
	  }
	  //如果类已链接则返回
	  if (this_oop->is_linked()) {
	    return true;
	  }
	 
	  assert(THREAD->is_Java_thread(), "non-JavaThread in link_class_impl");
	  JavaThread* jt = (JavaThread*)THREAD;
	 
	  instanceKlassHandle super(THREAD, this_oop->super());
	  if (super.not_null()) {
	    //如果父类是一个接口则抛出异常
	    if (super->is_interface()) {  
	      ResourceMark rm(THREAD);
	      Exceptions::fthrow(
	        THREAD_AND_LOCATION,
	        vmSymbols::java_lang_IncompatibleClassChangeError(),
	        "class %s has interface %s as super class",
	        this_oop->external_name(),
	        super->external_name()
	      );
	      return false;
	    }
	    //递归,完成父类的链接
	    link_class_impl(super, throw_verifyerror, CHECK_false);
	  }
	 
	  //完成当前类实现的所有接口的链接
	  Array<Klass*>* interfaces = this_oop->local_interfaces();
	  int num_interfaces = interfaces->length();
	  for (int index = 0; index < num_interfaces; index++) {
	    HandleMark hm(THREAD);
	    instanceKlassHandle ih(THREAD, interfaces->at(index));
	    link_class_impl(ih, throw_verifyerror, CHECK_false);
	  }
	 
	  //某些情况下链接父类的时候会把子类链接了,此时做检查是否已链接
	  if (this_oop->is_linked()) {
	    return true;
	  }
	 
	  {
	    //初始化对象锁
	    oop init_lock = this_oop->init_lock();
	    ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
	    
	    //已连接
	    if (!this_oop->is_linked()) {
	      //重写,重定位过的,不在进行验证
	      if (!this_oop->is_rewritten()) {
	        {
	          //完成字节码验证
	          bool verify_ok = verify_code(this_oop, throw_verifyerror, THREAD);
	          if (!verify_ok) {
	            return false;
	          }
	        }
	 
	        //再次校验是否验证完成
	        if (this_oop->is_linked()) {
	          return true;
	        }
	 
	        //重写支持更好的解释器运行性能,向常量池添加缓存cache
	        //并调整相应字节码的常量池索引,指向cache
	        this_oop->rewrite_class(CHECK_false);
	      } else if (this_oop()->is_shared()) {
	        ResourceMark rm(THREAD);
	        char* message_buffer; 
	        Handle loader = this_oop()->class_loader();
	        Handle pd     = this_oop()->protection_domain();
	        //依赖约束检查
	        bool verified = SystemDictionaryShared::check_verification_dependencies(this_oop(),
	                        loader, pd, &message_buffer, THREAD);
	        if (!verified) {
	          THROW_MSG_(vmSymbols::java_lang_VerifyError(), message_buffer, false);
	        }
	      }
	 
	      //重定位,为java方法配置解释器或者编译器入口
	      //完成方法链接,即方法的入参和返回值的类型的链接
	      this_oop->link_methods(CHECK_false);
	      //初始化vtable和itable
	      ClassLoaderData * loader_data = this_oop->class_loader_data();
	      if (!(this_oop()->is_shared() &&
	            loader_data->is_the_null_class_loader_data())) {
	        ResourceMark rm(THREAD);
	        this_oop->vtable()->initialize_vtable(true, CHECK_false);
	        this_oop->itable()->initialize_itable(true, CHECK_false);
	      }
	      //设置类的状态为链接完成
	      this_oop->set_init_state(linked);
	      if (JvmtiExport::should_post_class_prepare()) {
	        Thread *thread = THREAD;
	        assert(thread->is_Java_thread(), "thread->is_Java_thread()");
	        //发布JVMTI事件
	        JvmtiExport::post_class_prepare((JavaThread *) thread, this_oop());
	      }
	    }
	  }
	  return true;
	}
}

类的状态转换

在这里插入图片描述

  1. 加载,类加载器加载的过程中会对类文件做格式检查
  2. 链接,对加载到内存的类文件的二进制数据做约束检查(验证),静态字段设置默认值(准备),将常量池中的符合解析成正确的内存地址调用(解析)
  3. 初始化,就是类的静态属性的初始化

此过程对象拥有以下7种状态在这里插入图片描述

加载

加载过程主要体现在ClassLoader.load_classfile方法中,其它核心部分为
ClassFileParser.parseClassFile。就是把class文件的内容(有规则的,oop-klass模型)放到内存。

1.使用-XX:+TraceClassLoadingPreorder,会写出

[Loading ClassFileTest from file:/Users/moyao/IdeaProjects/simple/out/production/simple/]

2.类解析器将按虚拟机规范定义从Class文件格式读取数据,并对数据进行加工(此图出自《hotspot实战》,和openjdk8有所出入)
在这里插入图片描述

3.使用-XX:+TraceClassLoading,会写出

[Loaded ClassFileTest from file:/Users/moyao/IdeaProjects/simple/out/production/simple/]

4.使用-XX:+TraceClassResolution,会写出,

#哪个类来自哪个文件
RESOLVE ClassFileTest java.lang.Object ClassFileTest.java:1
链接

连接过程主要体现在InstanceKlass.bool link_class_impl方法中,就把各个class串连起来,形成一个整体。
在这里插入图片描述

验证

验证阶段,确保类或接口的二进制信息有效性。

使用-XX:+UnlockDiagnosticVMOptions -XX:+VerboseVerification 或者-XX:+TraceClassInitialization,会写出

Verifying class ClassFileTest with new format
Verifying method ClassFileTest.<init>()V
StackMapTable: frame_count = 0
table = { 
 }
Verifying method ClassFileTest.main([Ljava/lang/String;)V
StackMapTable: frame_count = 0
table = { 
 }
Verifying method ClassFileTest.getA()I
StackMapTable: frame_count = 0
table = { 
 }
End class verification for: ClassFileTest
准备

准备阶段的任务是创建类或者接口的静态字段,并用默认值初始化这些字段(final static 声明的会在些阶段设置,其它的只会设置默认值),这个阶段不会执行任何的虚拟机指令,在初始化阶段会有显示的初始化器来初始化这些字段,所以准备阶段不做初始化。
在类创建之后的任何时间,任何时间都可以执行准备,但一定要保证在初始化阶段前完成。

默认值初始化静态字段
ClassFileParser::parseClassFile
 java_lang_Class::create_mirror

解析

解析是根据运行时常量池里的符号引用来动态决定具体值的过程,其目标主要是将常量池中的4种符号引用转换成直接引用(运行时实际地址)。

  1. 接口
  2. 字段
  3. 类方法和接口方法

主要的解析方法
link_class_impl
  rewrite_class

初始化

初始化对类和接口来说就是执行它的初始化方法,只有在发生下列行为时,类或者接口才会被初始化:

  1. 执行new,getstatic,putstatic,invokestatic指令时
  2. 初次调用方法句柄java.lang.invoke.MethodHanlder实例,该实例的种类是REF_getstatic,REF_putstatic,REF_invokestatic
  3. 调用Class类或者反射类库中的某些反射方法
  4. 对类的某个子类进行初始化时
  5. 该类被选定为Java虚拟机启动时的初始类

主要的初始化方法
InstanceKlass:: initialize_impl

主要参考

《hotspot实战》
《Java虚拟机规范8版》
Hotspot 类加载、链接和初始化

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值