2.HotSpot如何加载并解析class文件
文章目录
- 2.1前言
- 2.2 类如何加载
- 第一步:双亲委派加载类,java顶层实现
- 第二步:找到defneClass1的native方法,开始进入JVM源码
- 常量池解析`parse_constant_pool`讲解
2.1前言
class文件在JVM整个生命周期包括了加载、验证、准备、解析、初始化、使用、卸载等7个阶段,Java层面通过ClassLoader.loadClass方法可以手动加载一个java类到虚拟机中,并返回Class类型的引用。
2.2 类如何加载
第一步:双亲委派加载类,java顶层实现
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
// 首先检查是否这个类已经被加载(后续会讲是如何检查的)
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
//如果当前的ClassLoader的parent!=null,首先让parent进行加载。
//如果想多进行了解,可以看双亲委派机制,这样做的目的是什么?
if (parent != null) {
c = parent.loadClass(name, false);
} else {
//如果parent则说明当前的parent是bootstrapClassLoader(是由C++实现的,所以为null)
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
// 如果类还是为null
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
// 一般我们继承classLoader 不会重写loadClass方法,不会打破双亲委派机制,一般都会重写findClass方法。
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
在findClass中调用了defineClass,顺着调用链去找,最终调用defineClass1的native方法。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aKejPEdO-1591858909752)(/Users/zhangwanyi/Library/Application Support/typora-user-images/image-20200610160840742.png)]
第二步:找到defneClass1的native方法,开始进入JVM源码
NIEXPORT jclass JNICALL
Java_java_lang_ClassLoader_defineClass1(JNIEnv *env,
jobject loader,
jstring name,
jbyteArray data,
jint offset,
jint length,
jobject pd,
jstring source){
//主要的方法,其余的判断赋值等省略
result = JVM_DefineClassWithSource(env, utfName, loader, body, length, pd, utfSource);
return result;
}
JVM_DefineClassWithSource \JVM_DefineClass()\JVM_DefineClassWithSourceCond()统一实现方法:
jvm.cpp::jvm_define_class_common
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);
//调用 jvm_define_class_common方法
return jvm_define_class_common(env, name, loader, buf, len, pd, source, true, THREAD);
JVM_END
`jvm.cpp::jvm_define_class_common
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__";
///部分代码省略
JavaThread* jt = (JavaThread*) THREAD;
if (UsePerfData) {
ClassLoader::perf_app_classfile_bytes_read()->inc(len);
}
// 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.
// 检查name为null,则可以初始化,因此无需检查.class中的类名
TempNewSymbol class_name = NULL;
if (name != NULL) {
const int str_len = (int)strlen(name);
// 检查str_len长度大于(1 << 16)-1 =>65535 主要是全限定名不支持大于65535,超过则 抛出NoClassDefFoundError
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);
}
// 创建一个Symbol用于存储全限定名
class_name = SymbolTable::new_symbol(name, str_len, CHECK_NULL);
}
ResourceMark rm(THREAD);
//类流文件指向source地址,读取相关信息
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));
//解析类文件并验证 重点方法,并生成Kiass文件
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());
}
进一步进入 SystemDictionary::resolve_from_stream ,里面最后调用了ClassFileParser::parseClassFile
,该方法用于解析class文件,里面代码非常长,我们重点讲解,要有耐心看完!
以下要对class类结构十分熟悉,如果不清楚,请先看文章:
https://blog.csdn.net/qq\_31430665/article/details/106281119 文章讲解《class文件解析,官方直译》
instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
ClassLoaderData* loader_data,
Handle protection_domain,
KlassHandle host_klass,
GrowableArray<Handle>* cp_patches,
TempNewSymbol& parsed_name,
bool verify,
TRAPS) {
JvmtiCachedClassFileData *cached_class_file = NULL;
Handle class_loader(THREAD, loader_data->class_loader());
bool has_default_methods = false;
bool declares_default_methods = false;
ResourceMark rm(THREAD);
ClassFileStream* cfs = stream();
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)
// 是否可以跳过验证,DumpSharedSpaces:共享的Metaspace空间dump到一个文件中
if (DumpSharedSpaces) {
// verify == true means it's a 'remote' class (i.e., non-boot class)
// Verification decision is based on BytecodeVerificationRemote flag
// for those classes.
// BytecodeVerificationRemote 为 true
// BytecodeVerificationLocal 为 false
_need_verify = (verify) ? BytecodeVerificationRemote :
BytecodeVerificationLocal;
} else {
// 如果 class_loader==null 或者verify=false 的时候 则不需要验证,即_need_verify=false
_need_verify = Verifier::should_verify_for(class_loader(), verify=false 的时候 );
}
// 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
// 获取magic 固定值:0xCAFEBABE
u4 magic = cfs->get_u4_fast();
guarantee_property(magic == JAVA_CLASSFILE_MAGIC,//0xCAFEBABE
"Incompatible magic value %u in class file %s",
magic, CHECK_(nullHandle));
// Version numbers
// 获取版本 minor_version=0,暂时没用到这个值
// major_version 为jdk版本,如jdk8 表示0X0034->52 jdk7->51 jdk6 ->50 jdk5->49
u2 minor_version = cfs->get_u2_fast();
u2 major_version = cfs->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, 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)) {
if (name == NULL) {
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_UnsupportedClassVersionError(),
"Unsupported class file version %u.%u, "
"this version of the Java Runtime only recognizes class file versions up to %u.%u",
major_version,
minor_version,
JAVA_MAX_SUPPORTED_VERSION,
JAVA_MAX_SUPPORTED_MINOR_VERSION);
} else {
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",
name->as_C_string(),
major_version,
minor_version,
JAVA_MAX_SUPPORTED_VERSION,
JAVA_MAX_SUPPORTED_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
// 解析常量池,常量池中有14种常量,后面仔细讲解,这里分别对常量进行进行流解析,并且分配空间
constantPoolHandle cp = parse_constant_pool(CHECK_(nullHandle));
//获取常量池中的length
int cp_size = cp->length();
cfs->guarantee_more(8, CHECK_(nullHandle)); // flags, this_class, super_class, infs_len
// Access flags
AccessFlags access_flags;
// 获取到类访问修饰符,比如作用域/可变性/继承/接口类型/是否用户代码生成等
// 看代码可知 JVM_RECOGNIZED_CLASS_MODIFIERS = 二进制 0111 0110 0011 0001 16进制7631
jint flags = cfs->get_u2_fast() & JVM_RECOGNIZED_CLASS_MODIFIERS;
// 如果有JVM_ACC_INTERFACE 修饰,
// 版本小于6 并且 有 JVM_ACC_INTERFACE状态
if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION) {
// Set abstract bit for old class files for backward compatibility
// 6版本以前没有INTERFACE 中都是采用 ABSTRACT 类的形式
flags |= JVM_ACC_ABSTRACT;
}
verify_legal_class_modifiers(flags, CHECK_(nullHandle));
access_flags.set_flags(flags);
// This class and superclass
// 获取 this_class_index 的index
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("]");
}
#if INCLUDE_CDS
if (DumpLoadedClassList != NULL && cfs->source() != NULL && classlist_file->is_open()) {
// Only dump the classes that can be stored into CDS archive
if (SystemDictionaryShared::is_sharing_possible(loader_data)) {
if (name != NULL) {
ResourceMark rm(THREAD);
classlist_file->print_cr("%s", name->as_C_string());
classlist_file->flush();
}
}
}
#endif
-------------------------------可忽略-------------------------------
//获取super_class
u2 super_class_index = cfs->get_u2_fast();
//从 JVM_CONSTANT_Class 常量池里获取
instanceKlassHandle super_klass = parse_super_class(super_class_index,
CHECK_NULL);
// Interfaces count
u2 itfs_len = cfs->get_u2_fast();
// 开始解析interfaces 后面会仔细讲解
Array<Klass*>* 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;
// 开始解析fields 后面会仔细讲解
Array<u2>* fields = parse_fields(class_name,
access_flags.is_interface(),
&fac, &java_fields_count,
CHECK_(nullHandle));
// Methods
// 进行Methods解析 后面会仔细讲解
bool has_final_method = false;
AccessFlags promoted_flags;
promoted_flags.set_flags(0);
Array<Method*>* methods = parse_methods(access_flags.is_interface(),
&promoted_flags,
&has_final_method,
&declares_default_methods,
CHECK_(nullHandle));
// 是否声明了默认的方法 (default 关键字,接口里支持)
if (declares_default_methods) {
has_default_methods = true;
}
// Additional attributes
// 属性解析 后面会仔细讲解
ClassAnnotationCollector parsed_annotations;
parse_classfile_attributes(&parsed_annotations, CHECK_(nullHandle));
// Finalize the Annotations metadata object,
// now that all annotation arrays have been created.
// 创建注解
create_combined_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类,为了做错误处理
_super_klass = super_klass;
// Compute the transitive list of all unique interfaces implemented by this class
// 通过super_klass 和 local_interfaces接口传递的接口
_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<Method*> 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]);
//将类加载的信息赋值给元数据
/**
//cp位常量池
_cp->set_pool_holder(this_klass());
//设置klass的常量池
this_klass->set_constants(_cp);
//设置该类的field字段
this_klass->set_fields(_fields, java_fields_count);
//设置该类的方法
this_klass->set_methods(_methods);
//设置该类的内部类
this_klass->set_inner_classes(_inner_classes);
//设置该类的接口
this_klass->set_local_interfaces(_local_interfaces);
this_klass->set_transitive_interfaces(_transitive_interfaces);
//设置该类的注解
this_klass->set_annotations(_combined_annotations);
//清除_cp,_fields,_methods,_inner_classes
clear_class_metadata();
*/
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
// 相关数据 赋值给klass
this_klass->set_minor_version(minor_version);
this_klass->set_major_version(major_version);
this_klass->set_has_default_methods(has_default_methods);
this_klass->set_declares_default_methods(declares_default_methods);
if (!host_klass.is_null()) {
assert (this_klass->is_anonymous(), "should be the same");
this_klass->set_host_klass(host_klass());
}
// 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
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
// 检查是否有super类的访问权限
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
// 检查是否重写了super的final方法
check_final_method_override(this_klass, CHECK_(nullHandle));
// check that if this class is an interface then it doesn't have static methods
// 检查是否this_klass是接口,它不能有静态方法
if (this_klass->is_interface()) {
/* An interface in a JAVA 8 classfile can be static */
// java8之后接口可以有静态方法(方法是静态&&方法名不是<cinit>)
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, class_loader, protection_domain,
CHECK_(nullHandle));
// Generate any default methods - default methods are interface methods
// that have a default implementation. This is new with Lambda project.
// 对default方法进行处理,有兴趣的可以看一看
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 */);
// 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;
return this_klass;
}
常量池解析parse_constant_pool
讲解
constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
//加载文件流
ClassFileStream* cfs = stream();
constantPoolHandle nullHandle;
cfs->guarantee_more(3, CHECK_(nullHandle)); // length, first cp tag
//获取常量池长度
u2 length = cfs->get_u2_fast();
guarantee_property(
length >= 1, "Illegal constant pool size %u in class file %s",
length, CHECK_(nullHandle));
ConstantPool* constant_pool = ConstantPool::allocate(_loader_data, length,
CHECK_(nullHandle));
//存储constant_pool->_cp
_cp = constant_pool; // save in case of errors
constantPoolHandle cp (THREAD, constant_pool);
// parsing constant pool entries
// 重点,解析常量池中的entity
// 主要是给_cp赋值,获取流中的数据
parse_constant_pool_entries(length, CHECK_(nullHandle));
int index = 1; // declared outside of loops for portability
// first verification pass - validate cross references and fixup class and string constants
// 遍历_cp中的值,分别进行校验
for (index = 1; index < length; index++) { // Index 0 is unused
jbyte tag = cp->tag_at(index).value();
switch (tag) {
case JVM_CONSTANT_Class :
ShouldNotReachHere(); // Only JVM_CONSTANT_ClassIndex should be present
break;
case JVM_CONSTANT_Fieldref :
// fall through
case JVM_CONSTANT_Methodref :
// fall through
//这块表明 JVM_CONSTANT_Fieldref、JVM_CONSTANT_Methodref、JVM_CONSTANT_InterfaceMethodref都先验证 nameAndType常量池和class_index,因为他们的结构是一样的
case JVM_CONSTANT_InterfaceMethodref : {
if (!_need_verify) break;
int klass_ref_index = cp->klass_ref_index_at(index);
int name_and_type_ref_index = cp->name_and_type_ref_index_at(index);
check_property(valid_klass_reference_at(klass_ref_index),
"Invalid constant pool index %u in class file %s",
klass_ref_index,
CHECK_(nullHandle));
check_property(valid_cp_range(name_and_type_ref_index, length) &&
cp->tag_at(name_and_type_ref_index).is_name_and_type(),
"Invalid constant pool index %u in class file %s",
name_and_type_ref_index,
CHECK_(nullHandle));
break;
}
case JVM_CONSTANT_String :
ShouldNotReachHere(); // Only JVM_CONSTANT_StringIndex should be present
break;
case JVM_CONSTANT_Integer :
break;
case JVM_CONSTANT_Float :
break;
case JVM_CONSTANT_Long :
case JVM_CONSTANT_Double :
index++;
// 跨过两位 index++ 因为 long和double都占用8字节,high_bytes,low_types
check_property(
(index < length && cp->tag_at(index).is_invalid()),
"Improper constant pool long/double index %u in class file %s",
index, CHECK_(nullHandle));
break;
case JVM_CONSTANT_NameAndType : {
if (!_need_verify) break;
//验证descriptor/name_index
int name_ref_index = cp->name_ref_index_at(index);
int signature_ref_index = cp->signature_ref_index_at(index);
check_property(valid_symbol_at(name_ref_index),
"Invalid constant pool index %u in class file %s",
name_ref_index, CHECK_(nullHandle));
check_property(valid_symbol_at(signature_ref_index),
"Invalid constant pool index %u in class file %s",
signature_ref_index, CHECK_(nullHandle));
break;
}
case JVM_CONSTANT_Utf8 :
break;
case JVM_CONSTANT_UnresolvedClass : // fall-through
case JVM_CONSTANT_UnresolvedClassInError:
ShouldNotReachHere(); // Only JVM_CONSTANT_ClassIndex should be present
break;
case JVM_CONSTANT_ClassIndex :
{
int class_index = cp->klass_index_at(index);
check_property(valid_symbol_at(class_index),
"Invalid constant pool index %u in class file %s",
class_index, CHECK_(nullHandle));
cp->unresolved_klass_at_put(index, cp->symbol_at(class_index));
}
break;
case JVM_CONSTANT_StringIndex :
{
int string_index = cp->string_index_at(index);
check_property(valid_symbol_at(string_index),
"Invalid constant pool index %u in class file %s",
string_index, CHECK_(nullHandle));
Symbol* sym = cp->symbol_at(string_index);
cp->unresolved_string_at_put(index, sym);
}
break;
case JVM_CONSTANT_MethodHandle :
{
int ref_index = cp->method_handle_index_at(index);
check_property(
valid_cp_range(ref_index, length) &&
EnableInvokeDynamic,
"Invalid constant pool index %u in class file %s",
ref_index, CHECK_(nullHandle));
constantTag tag = cp->tag_at(ref_index);
int ref_kind = cp->method_handle_ref_kind_at(index);
//reference_kind=1||2||3||4,指向CONSTANT_Fieldref_info索引,后面就这块就不细讲了,在class类结构里有
switch (ref_kind) {
case JVM_REF_getField:
case JVM_REF_getStatic:
case JVM_REF_putField:
case JVM_REF_putStatic:
check_property(
tag.is_field(),
"Invalid constant pool index %u in class file %s (not a field)",
ref_index, CHECK_(nullHandle));
break;
case JVM_REF_invokeVirtual:
case JVM_REF_newInvokeSpecial:
check_property(
tag.is_method(),
"Invalid constant pool index %u in class file %s (not a method)",
ref_index, CHECK_(nullHandle));
break;
case JVM_REF_invokeStatic:
case JVM_REF_invokeSpecial:
check_property(tag.is_method() ||
((_major_version >= JAVA_8_VERSION) && tag.is_interface_method()),
"Invalid constant pool index %u in class file %s (not a method)",
ref_index, CHECK_(nullHandle));
break;
case JVM_REF_invokeInterface:
check_property(
tag.is_interface_method(),
"Invalid constant pool index %u in class file %s (not an interface method)",
ref_index, CHECK_(nullHandle));
break;
default:
classfile_parse_error(
"Bad method handle kind at constant pool index %u in class file %s",
index, CHECK_(nullHandle));
}
// Keep the ref_index unchanged. It will be indirected at link-time.
}
break;
case JVM_CONSTANT_MethodType :
{
int ref_index = cp->method_type_index_at(index);
check_property(valid_symbol_at(ref_index) && EnableInvokeDynamic,
"Invalid constant pool index %u in class file %s",
ref_index, CHECK_(nullHandle));
}
break;
case JVM_CONSTANT_InvokeDynamic :
{
int name_and_type_ref_index = cp->invoke_dynamic_name_and_type_ref_index_at(index);
check_property(valid_cp_range(name_and_type_ref_index, length) &&
cp->tag_at(name_and_type_ref_index).is_name_and_type(),
"Invalid constant pool index %u in class file %s",
name_and_type_ref_index,
CHECK_(nullHandle));
// bootstrap specifier index must be checked later, when BootstrapMethods attr is available
break;
}
default:
fatal(err_msg("bad constant pool tag value %u",
cp->tag_at(index).value()));
ShouldNotReachHere();
break;
} // end of switch
} // end of for
if (_cp_patches != NULL) {
// need to treat this_class specially...
assert(EnableInvokeDynamic, "");
int this_class_index;
{
cfs->guarantee_more(8, CHECK_(nullHandle)); // flags, this_class, super_class, infs_len
u1* mark = cfs->current();
u2 flags = cfs->get_u2_fast();
this_class_index = cfs->get_u2_fast();
cfs->set_current(mark); // revert to mark
}
for (index = 1; index < length; index++) { // Index 0 is unused
if (has_cp_patch_at(index)) {
guarantee_property(index != this_class_index,
"Illegal constant pool patch to self at %d in class file %s",
index, CHECK_(nullHandle));
patch_constant_pool(cp, index, cp_patch_at(index), CHECK_(nullHandle));
}
}
}
if (!_need_verify) {
return cp;
}
// second verification pass - checks the strings are of the right format.
// but not yet to the other entries
// 第二步验证通过,检查string的格式
for (index = 1; index < length; index++) {
jbyte tag = cp->tag_at(index).value();
switch (tag) {
case JVM_CONSTANT_UnresolvedClass: {
Symbol* class_name = cp->unresolved_klass_at(index);
// check the name, even if _cp_patches will overwrite it
verify_legal_class_name(class_name, CHECK_(nullHandle));
break;
}
case JVM_CONSTANT_NameAndType: {
if (_need_verify && _major_version >= JAVA_7_VERSION) {
int sig_index = cp->signature_ref_index_at(index);
int name_index = cp->name_ref_index_at(index);
Symbol* name = cp->symbol_at(name_index);
Symbol* sig = cp->symbol_at(sig_index);
if (sig->byte_at(0) == JVM_SIGNATURE_FUNC) {
verify_legal_method_signature(name, sig, CHECK_(nullHandle));
} else {
verify_legal_field_signature(name, sig, CHECK_(nullHandle));
}
}
break;
}
case JVM_CONSTANT_InvokeDynamic:
case JVM_CONSTANT_Fieldref:
case JVM_CONSTANT_Methodref:
case JVM_CONSTANT_InterfaceMethodref: {
int name_and_type_ref_index = cp->name_and_type_ref_index_at(index);
// already verified to be utf8
int name_ref_index = cp->name_ref_index_at(name_and_type_ref_index);
// already verified to be utf8
int signature_ref_index = cp->signature_ref_index_at(name_and_type_ref_index);
Symbol* name = cp->symbol_at(name_ref_index);
Symbol* signature = cp->symbol_at(signature_ref_index);
if (tag == JVM_CONSTANT_Fieldref) {
verify_legal_field_name(name, CHECK_(nullHandle));
if (_need_verify && _major_version >= JAVA_7_VERSION) {
// Signature is verified above, when iterating NameAndType_info.
// Need only to be sure it's the right type.
if (signature->byte_at(0) == JVM_SIGNATURE_FUNC) {
throwIllegalSignature(
"Field", name, signature, CHECK_(nullHandle));
}
} else {
verify_legal_field_signature(name, signature, CHECK_(nullHandle));
}
} else {
verify_legal_method_name(name, CHECK_(nullHandle));
if (_need_verify && _major_version >= JAVA_7_VERSION) {
// Signature is verified above, when iterating NameAndType_info.
// Need only to be sure it's the right type.
if (signature->byte_at(0) != JVM_SIGNATURE_FUNC) {
throwIllegalSignature(
"Method", name, signature, CHECK_(nullHandle));
}
} else {
verify_legal_method_signature(name, signature, CHECK_(nullHandle));
}
if (tag == JVM_CONSTANT_Methodref) {
// 4509014: If a class method name begins with '<', it must be "<init>".
assert(name != NULL, "method name in constant pool is null");
unsigned int name_len = name->utf8_length();
assert(name_len > 0, "bad method name"); // already verified as legal name
if (name->byte_at(0) == '<') {
if (name != vmSymbols::object_initializer_name()) {
classfile_parse_error(
"Bad method name at constant pool index %u in class file %s",
name_ref_index, CHECK_(nullHandle));
}
}
}
}
break;
}
case JVM_CONSTANT_MethodHandle: {
int ref_index = cp->method_handle_index_at(index);
int ref_kind = cp->method_handle_ref_kind_at(index);
switch (ref_kind) {
case JVM_REF_invokeVirtual:
case JVM_REF_invokeStatic:
case JVM_REF_invokeSpecial:
case JVM_REF_newInvokeSpecial:
{
int name_and_type_ref_index = cp->name_and_type_ref_index_at(ref_index);
int name_ref_index = cp->name_ref_index_at(name_and_type_ref_index);
Symbol* name = cp->symbol_at(name_ref_index);
if (ref_kind == JVM_REF_newInvokeSpecial) {
if (name != vmSymbols::object_initializer_name()) {
classfile_parse_error(
"Bad constructor name at constant pool index %u in class file %s",
name_ref_index, CHECK_(nullHandle));
}
} else {
if (name == vmSymbols::object_initializer_name()) {
classfile_parse_error(
"Bad method name at constant pool index %u in class file %s",
name_ref_index, CHECK_(nullHandle));
}
}
}
break;
// Other ref_kinds are already fully checked in previous pass.
}
break;
}
case JVM_CONSTANT_MethodType: {
Symbol* no_name = vmSymbols::type_name(); // place holder
Symbol* signature = cp->method_type_signature_at(index);
verify_legal_method_signature(no_name, signature, CHECK_(nullHandle));
break;
}
case JVM_CONSTANT_Utf8: {
assert(cp->symbol_at(index)->refcount() != 0, "count corrupted");
}
} // end of switch
} // end of for
return cp;
}
还没有评论,来说两句吧...