JVM解析方法的代码如下:
Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,bool is_interface,
const ConstantPool* cp, AccessFlags* const promoted_flags, TRAPS){
...
}
JVM的字节码的方法访问标识和名称
1。首先创建ResourceMark记录当前Thread的resouceArea的资源使用,以便在析构函数时候释放资源空间.
ResourceMark rm(THREAD);
2. 对解析的方法的access_flags和name_index以及signature_index做校验。
//解析字节码流的2个字节的方法的access_flags
int flags = cfs->get_u2_fast();
//解析字节码流的2个字节的方法的name_index
const u2 name_index = cfs->get_u2_fast();
//获取常量池的长度,
const int cp_size = cp->length();
check_property(
valid_symbol_at(name_index),
"Illegal constant pool index %u for method name in class file %s",
name_index, CHECK_NULL);
// 获取常量池中name_index对应符号对象Symbol
const Symbol* const name = cp->symbol_at(name_index);
// 对应方法名称做校验
verify_legal_method_name(name, CHECK_NULL);
// 解析字节码流的2个字节的方法的signature_index
const u2 signature_index = cfs->get_u2_fast();
// 对signature_index做长度校验
guarantee_property(
valid_symbol_at(signature_index),
"Illegal constant pool index %u for method signature in class file %s",signature_index, CHECK_NULL);
// 获取signature_index的方法签名的符号对象
const Symbol* const signature = cp->symbol_at(signature_index);
3. 判断方法名称等于'clinit',则是类的初始化, 则校验方法的access_flags。
if (name == vmSymbols::class_initializer_name()) {
if (_major_version < 51) { // backward compatibility
flags = JVM_ACC_STATIC;
} else if ((flags & JVM_ACC_STATIC) == JVM_ACC_STATIC) {
flags &= JVM_ACC_STATIC | (_major_version <= JAVA_16_VERSION ? JVM_ACC_STRICT : 0);
} else {
classfile_parse_error("Method <clinit> is not static in class file %s", THREAD);
return NULL;
}
} else {
verify_legal_method_modifiers(flags, is_interface, name, CHECK_NULL);
}
4. 如果是接口并且方法名等于'init', 抛出接口不能有init的异常。
if (name == vmSymbols::object_initializer_name() && is_interface) {
classfile_parse_error("Interface cannot have a method named <init>, class file %s", THREAD);
return NULL;
}
5. 校验方法的名称和签名。
int args_size = -1;
if (_need_verify) {
verify_legal_name_with_signature(name, signature, CHECK_NULL);
// 如果静态字段
args_size = ((flags & JVM_ACC_STATIC) ? 0 : 1) +
verify_legal_method_signature(name, signature, CHECK_NULL);
if (args_size > MAX_ARGS_SIZE) {
classfile_parse_error("Too many arguments in method signature in class file %s", THREAD);
return NULL;
}
}
//创建AccessFlags对象
AccessFlags access_flags(flags & JVM_RECOGNIZED_METHOD_MODIFIERS);
解析方法字节码指令和异常属性
- 解析方法的字节码指令和异常属性。
//获取2个字节的方法属性个数
u2 method_attributes_count = cfs->get_u2_fast();
//开始遍历解析方法的属性
while (method_attributes_count--) {
cfs->guarantee_more(6, CHECK_NULL);
// 获取2个字节的方法的属性的名称的常量池索引
const u2 method_attribute_name_index = cfs->get_u2_fast();
//获取2个字节的方法的属性的长度
const u4 method_attribute_length = cfs->get_u4_fast();
// 获取常量池中方法属性索引的名称的符号
const Symbol* const method_attribute_name = cp->symbol_at(method_attribute_name_index);
// 判断方法属性的名称是否等于'Code'
if (method_attribute_name == vmSymbols::tag_code()) {
// 校验native和abstract是没有Code属性的
if (_need_verify) {
guarantee_property(
!access_flags.is_native() && !access_flags.is_abstract(), "Code attribute in native or abstract methods in class file %s",
CHECK_NULL);
}
//判断是否存在重复解析Code属性
if (parsed_code_attribute) {
classfile_parse_error("Multiple Code attributes in class file %s", THREAD);
return NULL;
}
//标识已经解析方法属性为true
parsed_code_attribute = true;
cfs->guarantee_more(8, CHECK_NULL);
//最大栈
max_stack = cfs->get_u2_fast();
//最大局部变量个数
max_locals = cfs->get_u2_fast();
//字节码指令的程度
code_length = cfs->get_u4_fast();
if (_need_verify) {
//校验参数长度小于最大局部变量
guarantee_property(args_size <= max_locals, "Arguments can't fit into locals in class file %s", CHECK_NULL);
// 校验字节码的长度大于0并且小于65535
guarantee_property(code_length > 0 && code_length <= MAX_CODE_SIZE,"Invalid method Code length %u in class file %s", code_length, CHECK_NULL);
}
// 字节码指令的开始指针
code_start = cfs->current();
assert(code_start != NULL, "null code start");
cfs->guarantee_more(code_length, CHECK_NULL);
//字节码的文件流跳过字节码指令的长度
cfs->skip_u1_fast(code_length);
// 接下里解析异常表
cfs->guarantee_more(2, CHECK_NULL);
// 获取2个字节的异常表的长度
exception_table_length = cfs->get_u2_fast();
// 解析异常表的开始位置
if (exception_table_length > 0) {
exception_table_start = parse_exception_table(cfs, code_length, exception_table_length, CHECK_NULL);
}
// 解析Code的附加属性
cfs->guarantee_more(2, CHECK_NULL);
// 从文件流中获取2个字节的Code属性的个数
u2 code_attributes_count = cfs->get_u2_fast();
unsigned int calculated_attribute_length = 0;
//计算属性长度
calculated_attribute_length =
sizeof(max_stack) + sizeof(max_locals) + sizeof(code_length);
calculated_attribute_length +=
code_length +
sizeof(exception_table_length) +
sizeof(code_attributes_count) +
exception_table_length *
(sizeof(u2) + // start_pc
sizeof(u2) + // end_pc
sizeof(u2) + // handler_pc
sizeof(u2) ); // catch_type_index
// 循环解析Code
while (code_attributes_count--) {
cfs->guarantee_more(6, CHECK_NULL); // code_attribute_name_index, code_attribute_length
const u2 code_attribute_name_index = cfs->get_u2_fast();
const u4 code_attribute_length = cfs->get_u4_fast();
calculated_attribute_length += code_attribute_length + sizeof(code_attribute_name_index) +
sizeof(code_attribute_length);
//校验code属性名称索引 check_property(valid_symbol_at(code_attribute_name_index),"Invalid code attribute name index %u in class file %s", code_attribute_name_index, CHECK_NULL);
//校验code行表
if (LoadLineNumberTables && cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_line_number_table()) {
//解析行表
parse_linenumber_table(code_attribute_length,
code_length,
&linenumber_table,
CHECK_NULL);
} else if (LoadLocalVariableTables &&cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_table()) {
// 解析本地变量表
if (!lvt_allocated) {
//在thread的resouceArea分配空间
localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2, INITIAL_MAX_LVT_NUMBER);
localvariable_table_start = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER);
localvariable_type_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2, INITIAL_MAX_LVT_NUMBER);
localvariable_type_table_start = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER);
lvt_allocated = true;
}
// 如果大於最大本地變量表,則重新分配原先2倍空间
if (lvt_cnt == max_lvt_cnt) {
max_lvt_cnt <<= 1;
localvariable_table_length = REALLOC_RESOURCE_ARRAY(u2, localvariable_table_length, lvt_cnt, max_lvt_cnt);
localvariable_table_start = REALLOC_RESOURCE_ARRAY(const unsafe_u2*, localvariable_table_start, lvt_cnt, max_lvt_cnt);
}
//解析本地变量表并保存
localvariable_table_start[lvt_cnt] =
parse_localvariable_table(cfs,
code_length, max_locals, code_attribute_length, &localvariable_table_length[lvt_cnt],
false, CHECK_NULL);
total_lvt_length += localvariable_table_length[lvt_cnt];
lvt_cnt++;
//解析本地变量表类型
} else if (LoadLocalVariableTypeTables &&
_major_version >= JAVA_1_5_VERSION &&
cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_type_table()) {
if (!lvt_allocated) {
//分配空间
localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2, INITIAL_MAX_LVT_NUMBER);
localvariable_table_start = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER);
localvariable_type_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2, INITIAL_MAX_LVT_NUMBER);
localvariable_type_table_start = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER);
lvt_allocated = true;
}
//解析本地表类型
if (lvtt_cnt == max_lvtt_cnt) {
max_lvtt_cnt <<= 1;
localvariable_type_table_length = REALLOC_RESOURCE_ARRAY(u2, localvariable_type_table_length, lvtt_cnt, max_lvtt_cnt);
localvariable_type_table_start = REALLOC_RESOURCE_ARRAY(const unsafe_u2*, localvariable_type_table_start, lvtt_cnt, max_lvtt_cnt);
}
// 解析本地变量表并保存
localvariable_type_table_start[lvtt_cnt] =
parse_localvariable_table(cfs,
code_length,
max_locals,
code_attribute_length,
&localvariable_type_table_length[lvtt_cnt],
true, CHECK_NULL);
lvtt_cnt++;
} else if (_major_version >= Verifier::STACKMAP_ATTRIBUTE_MAJOR_VERSION &&
cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_stack_map_table()) {
// 只有jdk1.6才有stackmap属性
if (parsed_stackmap_attribute) {
classfile_parse_error("Multiple StackMapTable attributes in class file %s", THREAD);
return NULL;
}
// 解析stackmap的数据
stackmap_data = parse_stackmap_table(cfs, code_attribute_length, _need_verify, CHECK_NULL);
stackmap_data_length = code_attribute_length;
parsed_stackmap_attribute = true;
} else {
// 跳过的位置属性
cfs->skip_u1(code_attribute_length, CHECK_NULL);
}
}
// 校验方法属性长度
if (_need_verify) {
guarantee_property(method_attribute_length == calculated_attribute_length, "Code segment has wrong length in class file %s",
CHECK_NULL);
}
} else if (method_attribute_name == vmSymbols::tag_exceptions()) {
// 解析受检异常属性
if (parsed_checked_exceptions_attribute) {
classfile_parse_error("Multiple Exceptions attributes in class file %s", THREAD);
return NULL;
}
parsed_checked_exceptions_attribute = true;
checked_exceptions_start =
parse_checked_exceptions(cfs,
&checked_exceptions_length, method_attribute_length,
CHECK_NULL);
} else if (method_attribute_name == vmSymbols::tag_method_parameters()) {
//解析方法参数
if (method_parameters_seen) {
classfile_parse_error("Multiple MethodParameters attributes in class file %s", THREAD);
return NULL;
}
method_parameters_seen = true;
//从文件流中获取一个字节的参数长度
method_parameters_length = cfs->get_u1_fast();
// 计算方法参数长度
const u2 real_length = (method_parameters_length * 4u) + 1u;
if (method_attribute_length != real_length) {
classfile_parse_error(
"Invalid MethodParameters method attribute length %u in class file",
method_attribute_length, THREAD);
return NULL;
}
//文件流中方法参数数据的指针
method_parameters_data = cfs->current();
cfs->skip_u2_fast(method_parameters_length);
cfs->skip_u2_fast(method_parameters_length);
// 如果不支持反射,则忽略这个
if (!vmClasses::Parameter_klass_loaded())
method_parameters_length = -1;
} else if (method_attribute_name == vmSymbols::tag_synthetic()) {
//如果方法属性名称是Synthetic,
if (method_attribute_length != 0) {
classfile_parse_error(
"Invalid Synthetic method attribute length %u in class file %s",
method_attribute_length, THREAD);
return NULL;
}
// 校验是否是编译器合成的方法
access_flags.set_is_synthetic();
} else if (method_attribute_name == vmSymbols::tag_deprecated()) {
// 方法属性
if (method_attribute_length != 0) {
classfile_parse_error(
"Invalid Deprecated method attribute length %u in class file %s",method_attribute_length, THREAD);
return NULL;
}
} else if (_major_version >= JAVA_1_5_VERSION) {
// 主版本号大于1.5
if (method_attribute_name == vmSymbols::tag_signature()) {
// 泛型签名索引
if (generic_signature_index != 0) {
classfile_parse_error(
"Multiple Signature attributes for method in class file %s",THREAD);
return NULL;
}
// 方法属性长度
if (method_attribute_length != 2) {
classfile_parse_error(
"Invalid Signature attribute length %u in class file %s",method_attribute_length, THREAD);
return NULL;
}
// 泛型签名索引
generic_signature_index = parse_generic_signature_attribute(cfs, CHECK_NULL);
} else if (method_attribute_name == vmSymbols::tag_runtime_visible_annotations()) {
if (runtime_visible_annotations != NULL) {
classfile_parse_error(
"Multiple RuntimeVisibleAnnotations attributes for method in class file %s",
THREAD);
return NULL;
}
// 运行时可见的注解
runtime_visible_annotations_length = method_attribute_length;
runtime_visible_annotations = cfs->current();
assert(runtime_visible_annotations != NULL, "null visible annotations");
cfs->guarantee_more(runtime_visible_annotations_length, CHECK_NULL);
// 解析运行时可见的注解
parse_annotations(cp,
runtime_visible_annotations, runtime_visible_annotations_length,
&parsed_annotations,
_loader_data,
_can_access_vm_annotations);
cfs->skip_u1_fast(runtime_visible_annotations_length);
} else if (method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
//运行时不可见注解
if (runtime_invisible_annotations_exists) {
classfile_parse_error(
"Multiple RuntimeInvisibleAnnotations attributes for method in class file %s",
THREAD);
return NULL;
}
runtime_invisible_annotations_exists = true;
if (PreserveAllAnnotations) {
runtime_invisible_annotations_length = method_attribute_length;
runtime_invisible_annotations = cfs->current();
assert(runtime_invisible_annotations != NULL, "null invisible annotations");
}
cfs->skip_u1(method_attribute_length, CHECK_NULL);
} else if (method_attribute_name == vmSymbols::tag_runtime_visible_parameter_annotations()) {
// 解析运行时不可见的注解
if (runtime_visible_parameter_annotations != NULL) {
classfile_parse_error(
"Multiple RuntimeVisibleParameterAnnotations attributes for method in class file %s",
THREAD);
return NULL;
}
runtime_visible_parameter_annotations_length = method_attribute_length;
// 运行时不可见的注解
runtime_visible_parameter_annotations = cfs->current();
cfs->skip_u1(runtime_visible_parameter_annotations_length, CHECK_NULL);
} else if (method_attribute_name == vmSymbols::tag_runtime_invisible_parameter_annotations()) {
if (runtime_invisible_parameter_annotations_exists) {
classfile_parse_error(
"Multiple RuntimeInvisibleParameterAnnotations attributes for method in class file %s",
THREAD);
return NULL;
}
runtime_invisible_parameter_annotations_exists = true;
if (PreserveAllAnnotations) {
runtime_invisible_parameter_annotations_length = method_attribute_length;
runtime_invisible_parameter_annotations = cfs->current();
assert(runtime_invisible_parameter_annotations != NULL,"null invisible parameter annotations");
}
cfs->skip_u1(method_attribute_length, CHECK_NULL);
} else if (method_attribute_name == vmSymbols::tag_annotation_default()) {
// 解析AnnotationDefault注解
if (annotation_default != NULL) {
classfile_parse_error(
"Multiple AnnotationDefault attributes for method in class file %s", THREAD);
return NULL;
}
annotation_default_length = method_attribute_length;
annotation_default = cfs->current();
assert(annotation_default != NULL, "null annotation default");
cfs->skip_u1(annotation_default_length, CHECK_NULL);
} else if (method_attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) {
// 解析运行时可见类型注解
if (runtime_visible_type_annotations != NULL) {
classfile_parse_error(
"Multiple RuntimeVisibleTypeAnnotations attributes for method in class file %s",
THREAD);
return NULL;
}
runtime_visible_type_annotations_length = method_attribute_length;
runtime_visible_type_annotations = cfs->current();
assert(runtime_visible_type_annotations != NULL, "null visible type annotations");
cfs->skip_u1(runtime_visible_type_annotations_length, CHECK_NULL);
} else if (method_attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) {
// 解析运行时不可见的类型注解
if (runtime_invisible_type_annotations_exists) {
classfile_parse_error(
"Multiple RuntimeInvisibleTypeAnnotations attributes for method in class file %s",
THREAD);
return NULL;
} else {
runtime_invisible_type_annotations_exists = true;
}
if (PreserveAllAnnotations) {
runtime_invisible_type_annotations_length = method_attribute_length;
runtime_invisible_type_annotations = cfs->current();
assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations");
}
cfs->skip_u1(method_attribute_length, CHECK_NULL);
} else {
// 跳过未知的属性
cfs->skip_u1(method_attribute_length, CHECK_NULL);
}
} else {
// 跳过未知的属性
cfs->skip_u1(method_attribute_length, CHECK_NULL);
}
}
创建Method对象
- 创建InlineTableSizes对象记录一个Method对象的信息的大小,
InlineTableSizes sizes(
total_lvt_length,
linenumber_table_length,
exception_table_length,
checked_exceptions_length,
method_parameters_length,
generic_signature_index,
runtime_visible_annotations_length +
runtime_invisible_annotations_length,
runtime_visible_parameter_annotations_length +
runtime_invisible_parameter_annotations_length,
runtime_visible_type_annotations_length +
runtime_invisible_type_annotations_length,
annotation_default_length,
0);
6. 调用Method的allocate为Method对象.通过MetaspaceObj重载的new在metaSpace中分配内存资源。
Method* const m = Method::allocate(_loader_data,
code_length,
access_flags,
&sizes,
ConstMethod::NORMAL,
_cp->symbol_at(name_index), CHECK_NULL);
7. 调用ConstMethod的allocate方法分配对象空间,同样也是通过MetaspaceObj重载的new在metaSpace中分配内存资源。
Method* Method::allocate(ClassLoaderData* loader_data,
int byte_code_size,
AccessFlags access_flags,
InlineTableSizes* sizes,
ConstMethod::MethodType method_type,
Symbol* name,
TRAPS) {
assert(!access_flags.is_native() || byte_code_size == 0,
"native methods should not contain byte codes");
ConstMethod* cm = ConstMethod::allocate(loader_data,
byte_code_size,
sizes,
method_type,
CHECK_NULL);
int size = Method::size(access_flags.is_native());
return new (loader_data, size, MetaspaceObj::MethodType, THREAD) Method(cm, access_flags, name);
}
8. 设置Method的对象的字段信息。
ClassLoadingService::add_class_method_size(m->size()*wordSize);
// 设置Method的字段信息
m->set_constants(_cp);
m->set_name_index(name_index);
m->set_signature_index(signature_index);
m->compute_from_signature(cp->symbol_at(signature_index));
assert(args_size < 0 || args_size == m->size_of_parameters(), "");
//设置code的属性:最大站 和 最大本地变量值
m->set_max_stack(max_stack);
m->set_max_locals(max_locals);
if (stackmap_data != NULL) {
m->constMethod()->copy_stackmap_data(_loader_data,
(u1*)stackmap_data,
stackmap_data_length,
CHECK_NULL);
}
//设置字节码的文件流的方法的字节码指令的开始位置的指针
m->set_code((u1*)code_start);
9.
// 拷贝代码行表
if (linenumber_table != NULL) {
memcpy(m->compressed_linenumber_table(),
linenumber_table->buffer(),
linenumber_table_length);
}
//拷贝异常表
if (exception_table_length > 0) {
Copy::conjoint_swap_if_needed<Endian::JAVA>(exception_table_start, m->exception_table_start(),
exception_table_length * sizeof(ExceptionTableElement), sizeof(u2));
}
// 拷贝方法参数
if (method_parameters_length > 0) {
MethodParametersElement* elem = m->constMethod()->method_parameters_start();
for (int i = 0; i < method_parameters_length; i++) {
elem[i].name_cp_index = Bytes::get_Java_u2((address)method_parameters_data);
method_parameters_data += 2;
elem[i].flags = Bytes::get_Java_u2((address)method_parameters_data);
method_parameters_data += 2;
}
}
// 拷贝受检异常表
if (checked_exceptions_length > 0) {
Copy::conjoint_swap_if_needed<Endian::JAVA>(checked_exceptions_start,m->checked_exceptions_start(),
checked_exceptions_length * sizeof(CheckedExceptionElement),
sizeof(u2));
}
// 拷贝本地变量表到ConstMethod
if (total_lvt_length > 0) {
promoted_flags->set_has_localvariable_table();
copy_localvariable_table(m->constMethod(),
lvt_cnt,
localvariable_table_length,
localvariable_table_start,
lvtt_cnt,
localvariable_type_table_length,
localvariable_type_table_start,
CHECK_NULL);
}
//
if (parsed_annotations.has_any_annotations())
parsed_annotations.apply_to(methodHandle(THREAD, m));
//设置隐藏类标志
if (is_hidden()) {
m->set_hidden(true);
}
// 拷贝方法注解到ConstMethod
copy_method_annotations(m->constMethod(),
runtime_visible_annotations,
runtime_visible_annotations_length,
runtime_invisible_annotations,
runtime_invisible_annotations_length,
runtime_visible_parameter_annotations,
runtime_visible_parameter_annotations_length,
runtime_invisible_parameter_annotations, runtime_invisible_parameter_annotations_length,
runtime_visible_type_annotations,
runtime_visible_type_annotations_length,
runtime_invisible_type_annotations, runtime_invisible_type_annotations_length,
annotation_default,
annotation_default_length,
CHECK_NULL);
// 判断类的方法是finalize
if (InstanceKlass::is_finalization_enabled() &&
name == vmSymbols::finalize_method_name() &&
signature == vmSymbols::void_method_signature()) {
if (m->is_empty_method()) {
_has_empty_finalizer = true;
} else {
_has_finalizer = true;
}
}
// 判斷方法是 init 方法
if (name == vmSymbols::object_initializer_name() &&
signature == vmSymbols::void_method_signature() &&
m->is_vanilla_constructor()) {
_has_vanilla_constructor = true;
}
return m;
总结
本文主要分析JVM对class文件方法的字节码解析,主要涉及方法的名称、签名、字节码指令以及注解属性的解析, 并利用C++操作符对new的重载实现再metaspace分配空间资源,创建Method和ConstMethod对象。