8007320: NPG: move method annotations
Allocate method annotations and attach to ConstMethod if present Reviewed-by: dcubed, jiangli, sspitsyn, iklam
This commit is contained in:
parent
ee53020f94
commit
faea95b8d3
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -49,12 +49,18 @@ public class ConstMethod extends VMObject {
|
|||||||
private static int HAS_LOCALVARIABLE_TABLE;
|
private static int HAS_LOCALVARIABLE_TABLE;
|
||||||
private static int HAS_EXCEPTION_TABLE;
|
private static int HAS_EXCEPTION_TABLE;
|
||||||
private static int HAS_GENERIC_SIGNATURE;
|
private static int HAS_GENERIC_SIGNATURE;
|
||||||
|
private static int HAS_METHOD_ANNOTATIONS;
|
||||||
|
private static int HAS_PARAMETER_ANNOTATIONS;
|
||||||
|
private static int HAS_DEFAULT_ANNOTATIONS;
|
||||||
|
private static int HAS_TYPE_ANNOTATIONS;
|
||||||
|
|
||||||
|
private static final int sizeofShort = 2;
|
||||||
|
|
||||||
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
|
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
|
||||||
Type type = db.lookupType("ConstMethod");
|
Type type = db.lookupType("ConstMethod");
|
||||||
constants = new MetadataField(type.getAddressField("_constants"), 0);
|
constants = new MetadataField(type.getAddressField("_constants"), 0);
|
||||||
constMethodSize = new CIntField(type.getCIntegerField("_constMethod_size"), 0);
|
constMethodSize = new CIntField(type.getCIntegerField("_constMethod_size"), 0);
|
||||||
flags = new ByteField(type.getJByteField("_flags"), 0);
|
flags = new CIntField(type.getCIntegerField("_flags"), 0);
|
||||||
|
|
||||||
// enum constants for flags
|
// enum constants for flags
|
||||||
HAS_LINENUMBER_TABLE = db.lookupIntConstant("ConstMethod::_has_linenumber_table").intValue();
|
HAS_LINENUMBER_TABLE = db.lookupIntConstant("ConstMethod::_has_linenumber_table").intValue();
|
||||||
@ -62,6 +68,10 @@ public class ConstMethod extends VMObject {
|
|||||||
HAS_LOCALVARIABLE_TABLE = db.lookupIntConstant("ConstMethod::_has_localvariable_table").intValue();
|
HAS_LOCALVARIABLE_TABLE = db.lookupIntConstant("ConstMethod::_has_localvariable_table").intValue();
|
||||||
HAS_EXCEPTION_TABLE = db.lookupIntConstant("ConstMethod::_has_exception_table").intValue();
|
HAS_EXCEPTION_TABLE = db.lookupIntConstant("ConstMethod::_has_exception_table").intValue();
|
||||||
HAS_GENERIC_SIGNATURE = db.lookupIntConstant("ConstMethod::_has_generic_signature").intValue();
|
HAS_GENERIC_SIGNATURE = db.lookupIntConstant("ConstMethod::_has_generic_signature").intValue();
|
||||||
|
HAS_METHOD_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_method_annotations").intValue();
|
||||||
|
HAS_PARAMETER_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_parameter_annotations").intValue();
|
||||||
|
HAS_DEFAULT_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_default_annotations").intValue();
|
||||||
|
HAS_TYPE_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_type_annotations").intValue();
|
||||||
|
|
||||||
// Size of Java bytecodes allocated immediately after ConstMethod*.
|
// Size of Java bytecodes allocated immediately after ConstMethod*.
|
||||||
codeSize = new CIntField(type.getCIntegerField("_code_size"), 0);
|
codeSize = new CIntField(type.getCIntegerField("_code_size"), 0);
|
||||||
@ -92,7 +102,7 @@ public class ConstMethod extends VMObject {
|
|||||||
// Fields
|
// Fields
|
||||||
private static MetadataField constants;
|
private static MetadataField constants;
|
||||||
private static CIntField constMethodSize;
|
private static CIntField constMethodSize;
|
||||||
private static ByteField flags;
|
private static CIntField flags;
|
||||||
private static CIntField codeSize;
|
private static CIntField codeSize;
|
||||||
private static CIntField nameIndex;
|
private static CIntField nameIndex;
|
||||||
private static CIntField signatureIndex;
|
private static CIntField signatureIndex;
|
||||||
@ -123,7 +133,7 @@ public class ConstMethod extends VMObject {
|
|||||||
return constMethodSize.getValue(this);
|
return constMethodSize.getValue(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte getFlags() {
|
public long getFlags() {
|
||||||
return flags.getValue(this);
|
return flags.getValue(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,7 +263,7 @@ public class ConstMethod extends VMObject {
|
|||||||
public void iterateFields(MetadataVisitor visitor) {
|
public void iterateFields(MetadataVisitor visitor) {
|
||||||
visitor.doMetadata(constants, true);
|
visitor.doMetadata(constants, true);
|
||||||
visitor.doCInt(constMethodSize, true);
|
visitor.doCInt(constMethodSize, true);
|
||||||
visitor.doByte(flags, true);
|
visitor.doCInt(flags, true);
|
||||||
visitor.doCInt(codeSize, true);
|
visitor.doCInt(codeSize, true);
|
||||||
visitor.doCInt(nameIndex, true);
|
visitor.doCInt(nameIndex, true);
|
||||||
visitor.doCInt(signatureIndex, true);
|
visitor.doCInt(signatureIndex, true);
|
||||||
@ -381,6 +391,22 @@ public class ConstMethod extends VMObject {
|
|||||||
return (getFlags() & HAS_GENERIC_SIGNATURE) != 0;
|
return (getFlags() & HAS_GENERIC_SIGNATURE) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasMethodAnnotations() {
|
||||||
|
return (getFlags() & HAS_METHOD_ANNOTATIONS) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasParameterAnnotations() {
|
||||||
|
return (getFlags() & HAS_PARAMETER_ANNOTATIONS) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasDefaultAnnotations() {
|
||||||
|
return (getFlags() & HAS_DEFAULT_ANNOTATIONS) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasTypeAnnotations() {
|
||||||
|
return (getFlags() & HAS_TYPE_ANNOTATIONS) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Internals only below this point
|
// Internals only below this point
|
||||||
@ -400,9 +426,15 @@ public class ConstMethod extends VMObject {
|
|||||||
return offsetOfCodeEnd() + (isNative() ? 2 * VM.getVM().getAddressSize() : 0);
|
return offsetOfCodeEnd() + (isNative() ? 2 * VM.getVM().getAddressSize() : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Offset of last short in Method*
|
// Offset of last short in Method* before annotations, if present
|
||||||
private long offsetOfLastU2Element() {
|
private long offsetOfLastU2Element() {
|
||||||
return getSize() * VM.getVM().getObjectHeap().getOopSize() - 2;
|
int offset = 0;
|
||||||
|
if (hasMethodAnnotations()) offset++;
|
||||||
|
if (hasParameterAnnotations()) offset++;
|
||||||
|
if (hasTypeAnnotations()) offset++;
|
||||||
|
if (hasDefaultAnnotations()) offset++;
|
||||||
|
long wordSize = VM.getVM().getObjectHeap().getOopSize();
|
||||||
|
return (getSize() * wordSize) - (offset * wordSize) - sizeofShort;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Offset of the generic signature index
|
// Offset of the generic signature index
|
||||||
@ -411,7 +443,7 @@ public class ConstMethod extends VMObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private long offsetOfCheckedExceptionsLength() {
|
private long offsetOfCheckedExceptionsLength() {
|
||||||
return hasGenericSignature() ? offsetOfLastU2Element() - 2 :
|
return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :
|
||||||
offsetOfLastU2Element();
|
offsetOfLastU2Element();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,11 +493,11 @@ public class ConstMethod extends VMObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hasExceptionTable()) {
|
if (hasExceptionTable()) {
|
||||||
return offsetOfExceptionTable() - 2;
|
return offsetOfExceptionTable() - sizeofShort;
|
||||||
} else if (hasCheckedExceptions()) {
|
} else if (hasCheckedExceptions()) {
|
||||||
return offsetOfCheckedExceptions() - 2;
|
return offsetOfCheckedExceptions() - sizeofShort;
|
||||||
} else {
|
} else {
|
||||||
return hasGenericSignature() ? offsetOfLastU2Element() - 2 :
|
return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :
|
||||||
offsetOfLastU2Element();
|
offsetOfLastU2Element();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -493,9 +525,9 @@ public class ConstMethod extends VMObject {
|
|||||||
Assert.that(hasExceptionTable(), "should only be called if table is present");
|
Assert.that(hasExceptionTable(), "should only be called if table is present");
|
||||||
}
|
}
|
||||||
if (hasCheckedExceptions()) {
|
if (hasCheckedExceptions()) {
|
||||||
return offsetOfCheckedExceptions() - 2;
|
return offsetOfCheckedExceptions() - sizeofShort;
|
||||||
} else {
|
} else {
|
||||||
return hasGenericSignature() ? offsetOfLastU2Element() - 2 :
|
return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :
|
||||||
offsetOfLastU2Element();
|
offsetOfLastU2Element();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1856,6 +1856,154 @@ void ClassFileParser::ClassAnnotationCollector::apply_to(instanceKlassHandle k)
|
|||||||
#define MAX_CODE_SIZE 65535
|
#define MAX_CODE_SIZE 65535
|
||||||
#define INITIAL_MAX_LVT_NUMBER 256
|
#define INITIAL_MAX_LVT_NUMBER 256
|
||||||
|
|
||||||
|
/* Copy class file LVT's/LVTT's into the HotSpot internal LVT.
|
||||||
|
*
|
||||||
|
* Rules for LVT's and LVTT's are:
|
||||||
|
* - There can be any number of LVT's and LVTT's.
|
||||||
|
* - If there are n LVT's, it is the same as if there was just
|
||||||
|
* one LVT containing all the entries from the n LVT's.
|
||||||
|
* - There may be no more than one LVT entry per local variable.
|
||||||
|
* Two LVT entries are 'equal' if these fields are the same:
|
||||||
|
* start_pc, length, name, slot
|
||||||
|
* - There may be no more than one LVTT entry per each LVT entry.
|
||||||
|
* Each LVTT entry has to match some LVT entry.
|
||||||
|
* - HotSpot internal LVT keeps natural ordering of class file LVT entries.
|
||||||
|
*/
|
||||||
|
void ClassFileParser::copy_localvariable_table(ConstMethod* cm,
|
||||||
|
int lvt_cnt,
|
||||||
|
u2* localvariable_table_length,
|
||||||
|
u2** localvariable_table_start,
|
||||||
|
int lvtt_cnt,
|
||||||
|
u2* localvariable_type_table_length,
|
||||||
|
u2** localvariable_type_table_start,
|
||||||
|
TRAPS) {
|
||||||
|
|
||||||
|
LVT_Hash** lvt_Hash = NEW_RESOURCE_ARRAY(LVT_Hash*, HASH_ROW_SIZE);
|
||||||
|
initialize_hashtable(lvt_Hash);
|
||||||
|
|
||||||
|
// To fill LocalVariableTable in
|
||||||
|
Classfile_LVT_Element* cf_lvt;
|
||||||
|
LocalVariableTableElement* lvt = cm->localvariable_table_start();
|
||||||
|
|
||||||
|
for (int tbl_no = 0; tbl_no < lvt_cnt; tbl_no++) {
|
||||||
|
cf_lvt = (Classfile_LVT_Element *) localvariable_table_start[tbl_no];
|
||||||
|
for (int idx = 0; idx < localvariable_table_length[tbl_no]; idx++, lvt++) {
|
||||||
|
copy_lvt_element(&cf_lvt[idx], lvt);
|
||||||
|
// If no duplicates, add LVT elem in hashtable lvt_Hash.
|
||||||
|
if (LVT_put_after_lookup(lvt, lvt_Hash) == false
|
||||||
|
&& _need_verify
|
||||||
|
&& _major_version >= JAVA_1_5_VERSION) {
|
||||||
|
clear_hashtable(lvt_Hash);
|
||||||
|
ConstantPool* cp = cm->constants();
|
||||||
|
classfile_parse_error("Duplicated LocalVariableTable attribute "
|
||||||
|
"entry for '%s' in class file %s",
|
||||||
|
cp->symbol_at(lvt->name_cp_index)->as_utf8(),
|
||||||
|
CHECK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// To merge LocalVariableTable and LocalVariableTypeTable
|
||||||
|
Classfile_LVT_Element* cf_lvtt;
|
||||||
|
LocalVariableTableElement lvtt_elem;
|
||||||
|
|
||||||
|
for (int tbl_no = 0; tbl_no < lvtt_cnt; tbl_no++) {
|
||||||
|
cf_lvtt = (Classfile_LVT_Element *) localvariable_type_table_start[tbl_no];
|
||||||
|
for (int idx = 0; idx < localvariable_type_table_length[tbl_no]; idx++) {
|
||||||
|
copy_lvt_element(&cf_lvtt[idx], &lvtt_elem);
|
||||||
|
int index = hash(&lvtt_elem);
|
||||||
|
LVT_Hash* entry = LVT_lookup(&lvtt_elem, index, lvt_Hash);
|
||||||
|
if (entry == NULL) {
|
||||||
|
if (_need_verify) {
|
||||||
|
clear_hashtable(lvt_Hash);
|
||||||
|
ConstantPool* cp = cm->constants();
|
||||||
|
classfile_parse_error("LVTT entry for '%s' in class file %s "
|
||||||
|
"does not match any LVT entry",
|
||||||
|
cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(),
|
||||||
|
CHECK);
|
||||||
|
}
|
||||||
|
} else if (entry->_elem->signature_cp_index != 0 && _need_verify) {
|
||||||
|
clear_hashtable(lvt_Hash);
|
||||||
|
ConstantPool* cp = cm->constants();
|
||||||
|
classfile_parse_error("Duplicated LocalVariableTypeTable attribute "
|
||||||
|
"entry for '%s' in class file %s",
|
||||||
|
cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(),
|
||||||
|
CHECK);
|
||||||
|
} else {
|
||||||
|
// to add generic signatures into LocalVariableTable
|
||||||
|
entry->_elem->signature_cp_index = lvtt_elem.descriptor_cp_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clear_hashtable(lvt_Hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data,
|
||||||
|
ConstMethod* cm,
|
||||||
|
u1* runtime_visible_annotations,
|
||||||
|
int runtime_visible_annotations_length,
|
||||||
|
u1* runtime_invisible_annotations,
|
||||||
|
int runtime_invisible_annotations_length,
|
||||||
|
u1* runtime_visible_parameter_annotations,
|
||||||
|
int runtime_visible_parameter_annotations_length,
|
||||||
|
u1* runtime_invisible_parameter_annotations,
|
||||||
|
int runtime_invisible_parameter_annotations_length,
|
||||||
|
u1* runtime_visible_type_annotations,
|
||||||
|
int runtime_visible_type_annotations_length,
|
||||||
|
u1* runtime_invisible_type_annotations,
|
||||||
|
int runtime_invisible_type_annotations_length,
|
||||||
|
u1* annotation_default,
|
||||||
|
int annotation_default_length,
|
||||||
|
TRAPS) {
|
||||||
|
|
||||||
|
AnnotationArray* a;
|
||||||
|
|
||||||
|
if (runtime_visible_annotations_length +
|
||||||
|
runtime_invisible_annotations_length > 0) {
|
||||||
|
a = assemble_annotations(loader_data,
|
||||||
|
runtime_visible_annotations,
|
||||||
|
runtime_visible_annotations_length,
|
||||||
|
runtime_invisible_annotations,
|
||||||
|
runtime_invisible_annotations_length,
|
||||||
|
CHECK);
|
||||||
|
cm->set_method_annotations(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runtime_visible_parameter_annotations_length +
|
||||||
|
runtime_invisible_parameter_annotations_length > 0) {
|
||||||
|
a = assemble_annotations(loader_data,
|
||||||
|
runtime_visible_parameter_annotations,
|
||||||
|
runtime_visible_parameter_annotations_length,
|
||||||
|
runtime_invisible_parameter_annotations,
|
||||||
|
runtime_invisible_parameter_annotations_length,
|
||||||
|
CHECK);
|
||||||
|
cm->set_parameter_annotations(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (annotation_default_length > 0) {
|
||||||
|
a = assemble_annotations(loader_data,
|
||||||
|
annotation_default,
|
||||||
|
annotation_default_length,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
CHECK);
|
||||||
|
cm->set_default_annotations(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runtime_visible_type_annotations_length +
|
||||||
|
runtime_invisible_type_annotations_length > 0) {
|
||||||
|
a = assemble_annotations(loader_data,
|
||||||
|
runtime_visible_type_annotations,
|
||||||
|
runtime_visible_type_annotations_length,
|
||||||
|
runtime_invisible_type_annotations,
|
||||||
|
runtime_invisible_type_annotations_length,
|
||||||
|
CHECK);
|
||||||
|
cm->set_type_annotations(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Note: the parse_method below is big and clunky because all parsing of the code and exceptions
|
// Note: the parse_method below is big and clunky because all parsing of the code and exceptions
|
||||||
// attribute is inlined. This is cumbersome to avoid since we inline most of the parts in the
|
// attribute is inlined. This is cumbersome to avoid since we inline most of the parts in the
|
||||||
// Method* to save footprint, so we only know the size of the resulting Method* when the
|
// Method* to save footprint, so we only know the size of the resulting Method* when the
|
||||||
@ -1869,10 +2017,6 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
|||||||
constantPoolHandle cp,
|
constantPoolHandle cp,
|
||||||
bool is_interface,
|
bool is_interface,
|
||||||
AccessFlags *promoted_flags,
|
AccessFlags *promoted_flags,
|
||||||
AnnotationArray** method_annotations,
|
|
||||||
AnnotationArray** method_parameter_annotations,
|
|
||||||
AnnotationArray** method_default_annotations,
|
|
||||||
AnnotationArray** method_type_annotations,
|
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
ClassFileStream* cfs = stream();
|
ClassFileStream* cfs = stream();
|
||||||
methodHandle nullHandle;
|
methodHandle nullHandle;
|
||||||
@ -2273,10 +2417,24 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// All sizing information for a Method* is finally available, now create it
|
// All sizing information for a Method* is finally available, now create it
|
||||||
|
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);
|
||||||
|
|
||||||
Method* m = Method::allocate(
|
Method* m = Method::allocate(
|
||||||
loader_data, code_length, access_flags, linenumber_table_length,
|
loader_data, code_length, access_flags, &sizes,
|
||||||
total_lvt_length, exception_table_length, checked_exceptions_length,
|
|
||||||
method_parameters_length, generic_signature_index,
|
|
||||||
ConstMethod::NORMAL, CHECK_(nullHandle));
|
ConstMethod::NORMAL, CHECK_(nullHandle));
|
||||||
|
|
||||||
ClassLoadingService::add_class_method_size(m->size()*HeapWordSize);
|
ClassLoadingService::add_class_method_size(m->size()*HeapWordSize);
|
||||||
@ -2347,107 +2505,37 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
|||||||
copy_u2_with_conversion((u2*) m->checked_exceptions_start(), checked_exceptions_start, size);
|
copy_u2_with_conversion((u2*) m->checked_exceptions_start(), checked_exceptions_start, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy class file LVT's/LVTT's into the HotSpot internal LVT.
|
// Copy class file LVT's/LVTT's into the HotSpot internal LVT.
|
||||||
*
|
|
||||||
* Rules for LVT's and LVTT's are:
|
|
||||||
* - There can be any number of LVT's and LVTT's.
|
|
||||||
* - If there are n LVT's, it is the same as if there was just
|
|
||||||
* one LVT containing all the entries from the n LVT's.
|
|
||||||
* - There may be no more than one LVT entry per local variable.
|
|
||||||
* Two LVT entries are 'equal' if these fields are the same:
|
|
||||||
* start_pc, length, name, slot
|
|
||||||
* - There may be no more than one LVTT entry per each LVT entry.
|
|
||||||
* Each LVTT entry has to match some LVT entry.
|
|
||||||
* - HotSpot internal LVT keeps natural ordering of class file LVT entries.
|
|
||||||
*/
|
|
||||||
if (total_lvt_length > 0) {
|
if (total_lvt_length > 0) {
|
||||||
int tbl_no, idx;
|
|
||||||
|
|
||||||
promoted_flags->set_has_localvariable_table();
|
promoted_flags->set_has_localvariable_table();
|
||||||
|
copy_localvariable_table(m->constMethod(), lvt_cnt,
|
||||||
LVT_Hash** lvt_Hash = NEW_RESOURCE_ARRAY(LVT_Hash*, HASH_ROW_SIZE);
|
localvariable_table_length,
|
||||||
initialize_hashtable(lvt_Hash);
|
localvariable_table_start,
|
||||||
|
lvtt_cnt,
|
||||||
// To fill LocalVariableTable in
|
localvariable_type_table_length,
|
||||||
Classfile_LVT_Element* cf_lvt;
|
localvariable_type_table_start, CHECK_NULL);
|
||||||
LocalVariableTableElement* lvt = m->localvariable_table_start();
|
|
||||||
|
|
||||||
for (tbl_no = 0; tbl_no < lvt_cnt; tbl_no++) {
|
|
||||||
cf_lvt = (Classfile_LVT_Element *) localvariable_table_start[tbl_no];
|
|
||||||
for (idx = 0; idx < localvariable_table_length[tbl_no]; idx++, lvt++) {
|
|
||||||
copy_lvt_element(&cf_lvt[idx], lvt);
|
|
||||||
// If no duplicates, add LVT elem in hashtable lvt_Hash.
|
|
||||||
if (LVT_put_after_lookup(lvt, lvt_Hash) == false
|
|
||||||
&& _need_verify
|
|
||||||
&& _major_version >= JAVA_1_5_VERSION ) {
|
|
||||||
clear_hashtable(lvt_Hash);
|
|
||||||
classfile_parse_error("Duplicated LocalVariableTable attribute "
|
|
||||||
"entry for '%s' in class file %s",
|
|
||||||
cp->symbol_at(lvt->name_cp_index)->as_utf8(),
|
|
||||||
CHECK_(nullHandle));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// To merge LocalVariableTable and LocalVariableTypeTable
|
|
||||||
Classfile_LVT_Element* cf_lvtt;
|
|
||||||
LocalVariableTableElement lvtt_elem;
|
|
||||||
|
|
||||||
for (tbl_no = 0; tbl_no < lvtt_cnt; tbl_no++) {
|
|
||||||
cf_lvtt = (Classfile_LVT_Element *) localvariable_type_table_start[tbl_no];
|
|
||||||
for (idx = 0; idx < localvariable_type_table_length[tbl_no]; idx++) {
|
|
||||||
copy_lvt_element(&cf_lvtt[idx], &lvtt_elem);
|
|
||||||
int index = hash(&lvtt_elem);
|
|
||||||
LVT_Hash* entry = LVT_lookup(&lvtt_elem, index, lvt_Hash);
|
|
||||||
if (entry == NULL) {
|
|
||||||
if (_need_verify) {
|
|
||||||
clear_hashtable(lvt_Hash);
|
|
||||||
classfile_parse_error("LVTT entry for '%s' in class file %s "
|
|
||||||
"does not match any LVT entry",
|
|
||||||
cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(),
|
|
||||||
CHECK_(nullHandle));
|
|
||||||
}
|
|
||||||
} else if (entry->_elem->signature_cp_index != 0 && _need_verify) {
|
|
||||||
clear_hashtable(lvt_Hash);
|
|
||||||
classfile_parse_error("Duplicated LocalVariableTypeTable attribute "
|
|
||||||
"entry for '%s' in class file %s",
|
|
||||||
cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(),
|
|
||||||
CHECK_(nullHandle));
|
|
||||||
} else {
|
|
||||||
// to add generic signatures into LocalVariableTable
|
|
||||||
entry->_elem->signature_cp_index = lvtt_elem.descriptor_cp_index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clear_hashtable(lvt_Hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parsed_annotations.has_any_annotations())
|
if (parsed_annotations.has_any_annotations())
|
||||||
parsed_annotations.apply_to(m);
|
parsed_annotations.apply_to(m);
|
||||||
*method_annotations = assemble_annotations(loader_data,
|
|
||||||
runtime_visible_annotations,
|
// Copy annotations
|
||||||
runtime_visible_annotations_length,
|
copy_method_annotations(loader_data, m->constMethod(),
|
||||||
runtime_invisible_annotations,
|
runtime_visible_annotations,
|
||||||
runtime_invisible_annotations_length,
|
runtime_visible_annotations_length,
|
||||||
CHECK_(nullHandle));
|
runtime_invisible_annotations,
|
||||||
*method_parameter_annotations = assemble_annotations(loader_data,
|
runtime_invisible_annotations_length,
|
||||||
runtime_visible_parameter_annotations,
|
runtime_visible_parameter_annotations,
|
||||||
runtime_visible_parameter_annotations_length,
|
runtime_visible_parameter_annotations_length,
|
||||||
runtime_invisible_parameter_annotations,
|
runtime_invisible_parameter_annotations,
|
||||||
runtime_invisible_parameter_annotations_length,
|
runtime_invisible_parameter_annotations_length,
|
||||||
CHECK_(nullHandle));
|
runtime_visible_type_annotations,
|
||||||
*method_default_annotations = assemble_annotations(loader_data,
|
runtime_visible_type_annotations_length,
|
||||||
annotation_default,
|
runtime_invisible_type_annotations,
|
||||||
annotation_default_length,
|
runtime_invisible_type_annotations_length,
|
||||||
NULL,
|
annotation_default,
|
||||||
0,
|
annotation_default_length,
|
||||||
CHECK_(nullHandle));
|
CHECK_NULL);
|
||||||
*method_type_annotations = assemble_annotations(loader_data,
|
|
||||||
runtime_visible_type_annotations,
|
|
||||||
runtime_visible_type_annotations_length,
|
|
||||||
runtime_invisible_type_annotations,
|
|
||||||
runtime_invisible_type_annotations_length,
|
|
||||||
CHECK_(nullHandle));
|
|
||||||
|
|
||||||
if (name == vmSymbols::finalize_method_name() &&
|
if (name == vmSymbols::finalize_method_name() &&
|
||||||
signature == vmSymbols::void_method_signature()) {
|
signature == vmSymbols::void_method_signature()) {
|
||||||
@ -2463,6 +2551,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
|||||||
_has_vanilla_constructor = true;
|
_has_vanilla_constructor = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NOT_PRODUCT(m->verify());
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2476,17 +2565,9 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
|
|||||||
bool is_interface,
|
bool is_interface,
|
||||||
AccessFlags* promoted_flags,
|
AccessFlags* promoted_flags,
|
||||||
bool* has_final_method,
|
bool* has_final_method,
|
||||||
Array<AnnotationArray*>** methods_annotations,
|
|
||||||
Array<AnnotationArray*>** methods_parameter_annotations,
|
|
||||||
Array<AnnotationArray*>** methods_default_annotations,
|
|
||||||
Array<AnnotationArray*>** methods_type_annotations,
|
|
||||||
bool* has_default_methods,
|
bool* has_default_methods,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
ClassFileStream* cfs = stream();
|
ClassFileStream* cfs = stream();
|
||||||
AnnotationArray* method_annotations = NULL;
|
|
||||||
AnnotationArray* method_parameter_annotations = NULL;
|
|
||||||
AnnotationArray* method_default_annotations = NULL;
|
|
||||||
AnnotationArray* method_type_annotations = NULL;
|
|
||||||
cfs->guarantee_more(2, CHECK_NULL); // length
|
cfs->guarantee_more(2, CHECK_NULL); // length
|
||||||
u2 length = cfs->get_u2_fast();
|
u2 length = cfs->get_u2_fast();
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
@ -2500,10 +2581,6 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
|
|||||||
methodHandle method = parse_method(loader_data,
|
methodHandle method = parse_method(loader_data,
|
||||||
cp, is_interface,
|
cp, is_interface,
|
||||||
promoted_flags,
|
promoted_flags,
|
||||||
&method_annotations,
|
|
||||||
&method_parameter_annotations,
|
|
||||||
&method_default_annotations,
|
|
||||||
&method_type_annotations,
|
|
||||||
CHECK_NULL);
|
CHECK_NULL);
|
||||||
|
|
||||||
if (method->is_final()) {
|
if (method->is_final()) {
|
||||||
@ -2514,38 +2591,6 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
|
|||||||
*has_default_methods = true;
|
*has_default_methods = true;
|
||||||
}
|
}
|
||||||
methods->at_put(index, method());
|
methods->at_put(index, method());
|
||||||
|
|
||||||
if (method_annotations != NULL) {
|
|
||||||
if (*methods_annotations == NULL) {
|
|
||||||
*methods_annotations =
|
|
||||||
MetadataFactory::new_array<AnnotationArray*>(loader_data, length, NULL, CHECK_NULL);
|
|
||||||
}
|
|
||||||
(*methods_annotations)->at_put(index, method_annotations);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method_parameter_annotations != NULL) {
|
|
||||||
if (*methods_parameter_annotations == NULL) {
|
|
||||||
*methods_parameter_annotations =
|
|
||||||
MetadataFactory::new_array<AnnotationArray*>(loader_data, length, NULL, CHECK_NULL);
|
|
||||||
}
|
|
||||||
(*methods_parameter_annotations)->at_put(index, method_parameter_annotations);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method_default_annotations != NULL) {
|
|
||||||
if (*methods_default_annotations == NULL) {
|
|
||||||
*methods_default_annotations =
|
|
||||||
MetadataFactory::new_array<AnnotationArray*>(loader_data, length, NULL, CHECK_NULL);
|
|
||||||
}
|
|
||||||
(*methods_default_annotations)->at_put(index, method_default_annotations);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method_type_annotations != NULL) {
|
|
||||||
if (*methods_type_annotations == NULL) {
|
|
||||||
*methods_type_annotations =
|
|
||||||
MetadataFactory::new_array<AnnotationArray*>(loader_data, length, NULL, CHECK_NULL);
|
|
||||||
}
|
|
||||||
(*methods_type_annotations)->at_put(index, method_type_annotations);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_need_verify && length > 1) {
|
if (_need_verify && length > 1) {
|
||||||
@ -2578,11 +2623,7 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
|
|||||||
|
|
||||||
Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
|
Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
|
||||||
Array<Method*>* methods,
|
Array<Method*>* methods,
|
||||||
Array<AnnotationArray*>* methods_annotations,
|
TRAPS) {
|
||||||
Array<AnnotationArray*>* methods_parameter_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_default_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_type_annotations,
|
|
||||||
TRAPS) {
|
|
||||||
int length = methods->length();
|
int length = methods->length();
|
||||||
// If JVMTI original method ordering or sharing is enabled we have to
|
// If JVMTI original method ordering or sharing is enabled we have to
|
||||||
// remember the original class file ordering.
|
// remember the original class file ordering.
|
||||||
@ -2598,10 +2639,7 @@ Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
|
|||||||
}
|
}
|
||||||
// Sort method array by ascending method name (for faster lookups & vtable construction)
|
// Sort method array by ascending method name (for faster lookups & vtable construction)
|
||||||
// Note that the ordering is not alphabetical, see Symbol::fast_compare
|
// Note that the ordering is not alphabetical, see Symbol::fast_compare
|
||||||
Method::sort_methods(methods, methods_annotations,
|
Method::sort_methods(methods);
|
||||||
methods_parameter_annotations,
|
|
||||||
methods_default_annotations,
|
|
||||||
methods_type_annotations);
|
|
||||||
|
|
||||||
// If JVMTI original method ordering or sharing is enabled construct int
|
// If JVMTI original method ordering or sharing is enabled construct int
|
||||||
// array remembering the original ordering
|
// array remembering the original ordering
|
||||||
@ -3048,9 +3086,6 @@ void ClassFileParser::apply_parsed_class_attributes(instanceKlassHandle k) {
|
|||||||
k->set_source_debug_extension(_sde_buffer, _sde_length);
|
k->set_source_debug_extension(_sde_buffer, _sde_length);
|
||||||
}
|
}
|
||||||
k->set_inner_classes(_inner_classes);
|
k->set_inner_classes(_inner_classes);
|
||||||
if (_annotations != NULL) {
|
|
||||||
k->annotations()->set_class_annotations(_annotations);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AnnotationArray* ClassFileParser::assemble_annotations(ClassLoaderData* loader_data,
|
AnnotationArray* ClassFileParser::assemble_annotations(ClassLoaderData* loader_data,
|
||||||
@ -3361,19 +3396,10 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||||||
bool has_final_method = false;
|
bool has_final_method = false;
|
||||||
AccessFlags promoted_flags;
|
AccessFlags promoted_flags;
|
||||||
promoted_flags.set_flags(0);
|
promoted_flags.set_flags(0);
|
||||||
|
|
||||||
Array<AnnotationArray*>* methods_annotations = NULL;
|
|
||||||
Array<AnnotationArray*>* methods_parameter_annotations = NULL;
|
|
||||||
Array<AnnotationArray*>* methods_default_annotations = NULL;
|
|
||||||
Array<AnnotationArray*>* methods_type_annotations = NULL;
|
|
||||||
Array<Method*>* methods = parse_methods(loader_data,
|
Array<Method*>* methods = parse_methods(loader_data,
|
||||||
cp, access_flags.is_interface(),
|
cp, access_flags.is_interface(),
|
||||||
&promoted_flags,
|
&promoted_flags,
|
||||||
&has_final_method,
|
&has_final_method,
|
||||||
&methods_annotations,
|
|
||||||
&methods_parameter_annotations,
|
|
||||||
&methods_default_annotations,
|
|
||||||
&methods_type_annotations,
|
|
||||||
&has_default_methods,
|
&has_default_methods,
|
||||||
CHECK_(nullHandle));
|
CHECK_(nullHandle));
|
||||||
|
|
||||||
@ -3432,10 +3458,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||||||
// sort methods
|
// sort methods
|
||||||
Array<int>* method_ordering = sort_methods(loader_data,
|
Array<int>* method_ordering = sort_methods(loader_data,
|
||||||
methods,
|
methods,
|
||||||
methods_annotations,
|
|
||||||
methods_parameter_annotations,
|
|
||||||
methods_default_annotations,
|
|
||||||
methods_type_annotations,
|
|
||||||
CHECK_(nullHandle));
|
CHECK_(nullHandle));
|
||||||
|
|
||||||
// promote flags from parse_methods() to the klass' flags
|
// promote flags from parse_methods() to the klass' flags
|
||||||
@ -4035,7 +4057,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||||||
const unsigned int total_oop_map_count =
|
const unsigned int total_oop_map_count =
|
||||||
compute_oop_map_count(super_klass, nonstatic_oop_map_count,
|
compute_oop_map_count(super_klass, nonstatic_oop_map_count,
|
||||||
first_nonstatic_oop_offset);
|
first_nonstatic_oop_offset);
|
||||||
|
|
||||||
// Compute reference type
|
// Compute reference type
|
||||||
ReferenceType rt;
|
ReferenceType rt;
|
||||||
if (super_klass() == NULL) {
|
if (super_klass() == NULL) {
|
||||||
@ -4057,7 +4078,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||||||
access_flags,
|
access_flags,
|
||||||
name,
|
name,
|
||||||
super_klass(),
|
super_klass(),
|
||||||
host_klass,
|
!host_klass.is_null(),
|
||||||
CHECK_(nullHandle));
|
CHECK_(nullHandle));
|
||||||
|
|
||||||
// Add all classes to our internal class loader list here,
|
// Add all classes to our internal class loader list here,
|
||||||
@ -4103,31 +4124,15 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||||||
if (is_anonymous()) // I am well known to myself
|
if (is_anonymous()) // I am well known to myself
|
||||||
cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
|
cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
|
||||||
|
|
||||||
// Allocate an annotation type if needed.
|
// Assign allocations if needed
|
||||||
if (fields_annotations != NULL ||
|
if (_annotations != NULL || _type_annotations != NULL ||
|
||||||
methods_annotations != NULL ||
|
fields_annotations != NULL || fields_type_annotations != NULL) {
|
||||||
methods_parameter_annotations != NULL ||
|
Annotations* annotations = Annotations::allocate(loader_data, CHECK_NULL);
|
||||||
methods_default_annotations != NULL ||
|
annotations->set_class_annotations(_annotations);
|
||||||
fields_type_annotations != NULL ||
|
annotations->set_class_type_annotations(_type_annotations);
|
||||||
methods_type_annotations != NULL) {
|
annotations->set_fields_annotations(fields_annotations);
|
||||||
Annotations* anno = Annotations::allocate(loader_data,
|
annotations->set_fields_type_annotations(fields_type_annotations);
|
||||||
fields_annotations, methods_annotations,
|
this_klass->set_annotations(annotations);
|
||||||
methods_parameter_annotations,
|
|
||||||
methods_default_annotations, CHECK_(nullHandle));
|
|
||||||
this_klass->set_annotations(anno);
|
|
||||||
} else {
|
|
||||||
this_klass->set_annotations(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fields_type_annotations != NULL ||
|
|
||||||
methods_type_annotations != NULL) {
|
|
||||||
assert(this_klass->annotations() != NULL, "annotations should have been allocated");
|
|
||||||
Annotations* anno = Annotations::allocate(loader_data,
|
|
||||||
fields_type_annotations,
|
|
||||||
methods_type_annotations,
|
|
||||||
NULL,
|
|
||||||
NULL, CHECK_(nullHandle));
|
|
||||||
this_klass->annotations()->set_type_annotations(anno);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this_klass->set_minor_version(minor_version);
|
this_klass->set_minor_version(minor_version);
|
||||||
@ -4153,27 +4158,8 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||||||
// Fill in field values obtained by parse_classfile_attributes
|
// Fill in field values obtained by parse_classfile_attributes
|
||||||
if (parsed_annotations.has_any_annotations())
|
if (parsed_annotations.has_any_annotations())
|
||||||
parsed_annotations.apply_to(this_klass);
|
parsed_annotations.apply_to(this_klass);
|
||||||
|
|
||||||
// Create annotations
|
|
||||||
if (_annotations != NULL && this_klass->annotations() == NULL) {
|
|
||||||
Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
|
|
||||||
this_klass->set_annotations(anno);
|
|
||||||
}
|
|
||||||
apply_parsed_class_attributes(this_klass);
|
apply_parsed_class_attributes(this_klass);
|
||||||
|
|
||||||
// Create type annotations
|
|
||||||
if (_type_annotations != NULL) {
|
|
||||||
if (this_klass->annotations() == NULL) {
|
|
||||||
Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
|
|
||||||
this_klass->set_annotations(anno);
|
|
||||||
}
|
|
||||||
if (this_klass->annotations()->type_annotations() == NULL) {
|
|
||||||
Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
|
|
||||||
this_klass->annotations()->set_type_annotations(anno);
|
|
||||||
}
|
|
||||||
this_klass->annotations()->type_annotations()->set_class_annotations(_type_annotations);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Miranda methods
|
// Miranda methods
|
||||||
if ((num_miranda_methods > 0) ||
|
if ((num_miranda_methods > 0) ||
|
||||||
// if this class introduced new miranda methods or
|
// if this class introduced new miranda methods or
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -199,29 +199,17 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
constantPoolHandle cp,
|
constantPoolHandle cp,
|
||||||
bool is_interface,
|
bool is_interface,
|
||||||
AccessFlags* promoted_flags,
|
AccessFlags* promoted_flags,
|
||||||
AnnotationArray** method_annotations,
|
|
||||||
AnnotationArray** method_parameter_annotations,
|
|
||||||
AnnotationArray** method_default_annotations,
|
|
||||||
AnnotationArray** method_type_annotations,
|
|
||||||
TRAPS);
|
TRAPS);
|
||||||
Array<Method*>* parse_methods(ClassLoaderData* loader_data,
|
Array<Method*>* parse_methods(ClassLoaderData* loader_data,
|
||||||
constantPoolHandle cp,
|
constantPoolHandle cp,
|
||||||
bool is_interface,
|
bool is_interface,
|
||||||
AccessFlags* promoted_flags,
|
AccessFlags* promoted_flags,
|
||||||
bool* has_final_method,
|
bool* has_final_method,
|
||||||
Array<AnnotationArray*>** methods_annotations,
|
|
||||||
Array<AnnotationArray*>** methods_parameter_annotations,
|
|
||||||
Array<AnnotationArray*>** methods_default_annotations,
|
|
||||||
Array<AnnotationArray*>** methods_type_annotations,
|
|
||||||
bool* has_default_method,
|
bool* has_default_method,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
Array<int>* sort_methods(ClassLoaderData* loader_data,
|
Array<int>* sort_methods(ClassLoaderData* loader_data,
|
||||||
Array<Method*>* methods,
|
Array<Method*>* methods,
|
||||||
Array<AnnotationArray*>* methods_annotations,
|
TRAPS);
|
||||||
Array<AnnotationArray*>* methods_parameter_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_default_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_type_annotations,
|
|
||||||
TRAPS);
|
|
||||||
u2* parse_exception_table(ClassLoaderData* loader_data,
|
u2* parse_exception_table(ClassLoaderData* loader_data,
|
||||||
u4 code_length, u4 exception_table_length,
|
u4 code_length, u4 exception_table_length,
|
||||||
constantPoolHandle cp, TRAPS);
|
constantPoolHandle cp, TRAPS);
|
||||||
@ -377,6 +365,32 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
: cp->tag_at(index).is_klass_reference());
|
: cp->tag_at(index).is_klass_reference());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void copy_localvariable_table(ConstMethod* cm, int lvt_cnt,
|
||||||
|
u2* localvariable_table_length,
|
||||||
|
u2** localvariable_table_start,
|
||||||
|
int lvtt_cnt,
|
||||||
|
u2* localvariable_type_table_length,
|
||||||
|
u2** localvariable_type_table_start,
|
||||||
|
TRAPS);
|
||||||
|
|
||||||
|
void copy_method_annotations(ClassLoaderData* loader_data,
|
||||||
|
ConstMethod* cm,
|
||||||
|
u1* runtime_visible_annotations,
|
||||||
|
int runtime_visible_annotations_length,
|
||||||
|
u1* runtime_invisible_annotations,
|
||||||
|
int runtime_invisible_annotations_length,
|
||||||
|
u1* runtime_visible_parameter_annotations,
|
||||||
|
int runtime_visible_parameter_annotations_length,
|
||||||
|
u1* runtime_invisible_parameter_annotations,
|
||||||
|
int runtime_invisible_parameter_annotations_length,
|
||||||
|
u1* runtime_visible_type_annotations,
|
||||||
|
int runtime_visible_type_annotations_length,
|
||||||
|
u1* runtime_invisible_type_annotations,
|
||||||
|
int runtime_invisible_type_annotations_length,
|
||||||
|
u1* annotation_default,
|
||||||
|
int annotation_default_length,
|
||||||
|
TRAPS);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
ClassFileParser(ClassFileStream* st) { set_stream(st); }
|
ClassFileParser(ClassFileStream* st) { set_stream(st); }
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -1146,9 +1146,10 @@ static Method* new_method(
|
|||||||
|
|
||||||
address code_start = static_cast<address>(bytecodes->adr_at(0));
|
address code_start = static_cast<address>(bytecodes->adr_at(0));
|
||||||
int code_length = bytecodes->length();
|
int code_length = bytecodes->length();
|
||||||
|
InlineTableSizes sizes;
|
||||||
|
|
||||||
Method* m = Method::allocate(cp->pool_holder()->class_loader_data(),
|
Method* m = Method::allocate(cp->pool_holder()->class_loader_data(),
|
||||||
code_length, flags, 0, 0, 0, 0, 0, 0,
|
code_length, flags, &sizes,
|
||||||
mt, CHECK_NULL);
|
mt, CHECK_NULL);
|
||||||
|
|
||||||
m->set_constants(NULL); // This will get filled in later
|
m->set_constants(NULL); // This will get filled in later
|
||||||
@ -1285,33 +1286,15 @@ static void merge_in_new_methods(InstanceKlass* klass,
|
|||||||
|
|
||||||
enum { ANNOTATIONS, PARAMETERS, DEFAULTS, NUM_ARRAYS };
|
enum { ANNOTATIONS, PARAMETERS, DEFAULTS, NUM_ARRAYS };
|
||||||
|
|
||||||
Array<AnnotationArray*>* original_annots[NUM_ARRAYS] = { NULL };
|
|
||||||
|
|
||||||
Array<Method*>* original_methods = klass->methods();
|
Array<Method*>* original_methods = klass->methods();
|
||||||
Annotations* annots = klass->annotations();
|
|
||||||
if (annots != NULL) {
|
|
||||||
original_annots[ANNOTATIONS] = annots->methods_annotations();
|
|
||||||
original_annots[PARAMETERS] = annots->methods_parameter_annotations();
|
|
||||||
original_annots[DEFAULTS] = annots->methods_default_annotations();
|
|
||||||
}
|
|
||||||
|
|
||||||
Array<int>* original_ordering = klass->method_ordering();
|
Array<int>* original_ordering = klass->method_ordering();
|
||||||
Array<int>* merged_ordering = Universe::the_empty_int_array();
|
Array<int>* merged_ordering = Universe::the_empty_int_array();
|
||||||
|
|
||||||
int new_size = klass->methods()->length() + new_methods->length();
|
int new_size = klass->methods()->length() + new_methods->length();
|
||||||
|
|
||||||
Array<AnnotationArray*>* merged_annots[NUM_ARRAYS];
|
|
||||||
|
|
||||||
Array<Method*>* merged_methods = MetadataFactory::new_array<Method*>(
|
Array<Method*>* merged_methods = MetadataFactory::new_array<Method*>(
|
||||||
klass->class_loader_data(), new_size, NULL, CHECK);
|
klass->class_loader_data(), new_size, NULL, CHECK);
|
||||||
for (int i = 0; i < NUM_ARRAYS; ++i) {
|
|
||||||
if (original_annots[i] != NULL) {
|
|
||||||
merged_annots[i] = MetadataFactory::new_array<AnnotationArray*>(
|
|
||||||
klass->class_loader_data(), new_size, CHECK);
|
|
||||||
} else {
|
|
||||||
merged_annots[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (original_ordering != NULL && original_ordering->length() > 0) {
|
if (original_ordering != NULL && original_ordering->length() > 0) {
|
||||||
merged_ordering = MetadataFactory::new_array<int>(
|
merged_ordering = MetadataFactory::new_array<int>(
|
||||||
klass->class_loader_data(), new_size, CHECK);
|
klass->class_loader_data(), new_size, CHECK);
|
||||||
@ -1338,12 +1321,6 @@ static void merge_in_new_methods(InstanceKlass* klass,
|
|||||||
(new_method == NULL || orig_method->name() < new_method->name())) {
|
(new_method == NULL || orig_method->name() < new_method->name())) {
|
||||||
merged_methods->at_put(i, orig_method);
|
merged_methods->at_put(i, orig_method);
|
||||||
original_methods->at_put(orig_idx, NULL);
|
original_methods->at_put(orig_idx, NULL);
|
||||||
for (int j = 0; j < NUM_ARRAYS; ++j) {
|
|
||||||
if (merged_annots[j] != NULL) {
|
|
||||||
merged_annots[j]->at_put(i, original_annots[j]->at(orig_idx));
|
|
||||||
original_annots[j]->at_put(orig_idx, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (merged_ordering->length() > 0) {
|
if (merged_ordering->length() > 0) {
|
||||||
merged_ordering->at_put(i, original_ordering->at(orig_idx));
|
merged_ordering->at_put(i, original_ordering->at(orig_idx));
|
||||||
}
|
}
|
||||||
@ -1372,21 +1349,9 @@ static void merge_in_new_methods(InstanceKlass* klass,
|
|||||||
|
|
||||||
// Replace klass methods with new merged lists
|
// Replace klass methods with new merged lists
|
||||||
klass->set_methods(merged_methods);
|
klass->set_methods(merged_methods);
|
||||||
if (annots != NULL) {
|
|
||||||
annots->set_methods_annotations(merged_annots[ANNOTATIONS]);
|
|
||||||
annots->set_methods_parameter_annotations(merged_annots[PARAMETERS]);
|
|
||||||
annots->set_methods_default_annotations(merged_annots[DEFAULTS]);
|
|
||||||
} else {
|
|
||||||
assert(merged_annots[ANNOTATIONS] == NULL, "Must be");
|
|
||||||
assert(merged_annots[PARAMETERS] == NULL, "Must be");
|
|
||||||
assert(merged_annots[DEFAULTS] == NULL, "Must be");
|
|
||||||
}
|
|
||||||
|
|
||||||
ClassLoaderData* cld = klass->class_loader_data();
|
ClassLoaderData* cld = klass->class_loader_data();
|
||||||
MetadataFactory::free_array(cld, original_methods);
|
MetadataFactory::free_array(cld, original_methods);
|
||||||
for (int i = 0; i < NUM_ARRAYS; ++i) {
|
|
||||||
MetadataFactory::free_array(cld, original_annots[i]);
|
|
||||||
}
|
|
||||||
if (original_ordering->length() > 0) {
|
if (original_ordering->length() > 0) {
|
||||||
klass->set_method_ordering(merged_ordering);
|
klass->set_method_ordering(merged_ordering);
|
||||||
MetadataFactory::free_array(cld, original_ordering);
|
MetadataFactory::free_array(cld, original_ordering);
|
||||||
|
@ -85,16 +85,20 @@
|
|||||||
"Number of bytes used by the InstanceKlass::singers() array") \
|
"Number of bytes used by the InstanceKlass::singers() array") \
|
||||||
f(class_annotations_bytes, class_annotations, \
|
f(class_annotations_bytes, class_annotations, \
|
||||||
"Size of class annotations") \
|
"Size of class annotations") \
|
||||||
|
f(class_type_annotations_bytes, class_type_annotations, \
|
||||||
|
"Size of class type annotations") \
|
||||||
f(fields_annotations_bytes, fields_annotations, \
|
f(fields_annotations_bytes, fields_annotations, \
|
||||||
"Size of field annotations") \
|
"Size of field annotations") \
|
||||||
|
f(fields_type_annotations_bytes, fields_type_annotations, \
|
||||||
|
"Size of field type annotations") \
|
||||||
f(methods_annotations_bytes, methods_annotations, \
|
f(methods_annotations_bytes, methods_annotations, \
|
||||||
"Size of method annotations") \
|
"Size of method annotations") \
|
||||||
f(methods_parameter_annotations_bytes, methods_parameter_annotations, \
|
f(methods_parameter_annotations_bytes, methods_parameter_annotations, \
|
||||||
"Size of method parameter annotations") \
|
"Size of method parameter annotations") \
|
||||||
|
f(methods_type_annotations_bytes, methods_type_annotations, \
|
||||||
|
"Size of methods type annotations") \
|
||||||
f(methods_default_annotations_bytes, methods_default_annotations, \
|
f(methods_default_annotations_bytes, methods_default_annotations, \
|
||||||
"Size of methods default annotations") \
|
"Size of methods default annotations") \
|
||||||
f(type_annotations_bytes, type_annotations, \
|
|
||||||
"Size of type annotations") \
|
|
||||||
f(annotations_bytes, annotations, \
|
f(annotations_bytes, annotations, \
|
||||||
"Size of all annotations") \
|
"Size of all annotations") \
|
||||||
f(cp_bytes, Cp, \
|
f(cp_bytes, Cp, \
|
||||||
|
@ -36,16 +36,8 @@ Annotations* Annotations::allocate(ClassLoaderData* loader_data, TRAPS) {
|
|||||||
return new (loader_data, size(), true, THREAD) Annotations();
|
return new (loader_data, size(), true, THREAD) Annotations();
|
||||||
}
|
}
|
||||||
|
|
||||||
Annotations* Annotations::allocate(ClassLoaderData* loader_data,
|
|
||||||
Array<AnnotationArray*>* fa,
|
|
||||||
Array<AnnotationArray*>* ma,
|
|
||||||
Array<AnnotationArray*>* mpa,
|
|
||||||
Array<AnnotationArray*>* mda, TRAPS) {
|
|
||||||
return new (loader_data, size(), true, THREAD) Annotations(fa, ma, mpa, mda);
|
|
||||||
}
|
|
||||||
|
|
||||||
// helper
|
// helper
|
||||||
static void free_contents(ClassLoaderData* loader_data, Array<AnnotationArray*>* p) {
|
void Annotations::free_contents(ClassLoaderData* loader_data, Array<AnnotationArray*>* p) {
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
for (int i = 0; i < p->length(); i++) {
|
for (int i = 0; i < p->length(); i++) {
|
||||||
MetadataFactory::free_array<u1>(loader_data, p->at(i));
|
MetadataFactory::free_array<u1>(loader_data, p->at(i));
|
||||||
@ -59,44 +51,16 @@ void Annotations::deallocate_contents(ClassLoaderData* loader_data) {
|
|||||||
MetadataFactory::free_array<u1>(loader_data, class_annotations());
|
MetadataFactory::free_array<u1>(loader_data, class_annotations());
|
||||||
}
|
}
|
||||||
free_contents(loader_data, fields_annotations());
|
free_contents(loader_data, fields_annotations());
|
||||||
free_contents(loader_data, methods_annotations());
|
|
||||||
free_contents(loader_data, methods_parameter_annotations());
|
|
||||||
free_contents(loader_data, methods_default_annotations());
|
|
||||||
|
|
||||||
// Recursively deallocate optional Annotations linked through this one
|
if (class_type_annotations() != NULL) {
|
||||||
MetadataFactory::free_metadata(loader_data, type_annotations());
|
MetadataFactory::free_array<u1>(loader_data, class_type_annotations());
|
||||||
|
}
|
||||||
|
free_contents(loader_data, fields_type_annotations());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the annotation at 'idnum' to 'anno'.
|
|
||||||
// We don't want to create or extend the array if 'anno' is NULL, since that is the
|
|
||||||
// default value. However, if the array exists and is long enough, we must set NULL values.
|
|
||||||
void Annotations::set_methods_annotations_of(instanceKlassHandle ik,
|
|
||||||
int idnum, AnnotationArray* anno,
|
|
||||||
Array<AnnotationArray*>** md_p,
|
|
||||||
TRAPS) {
|
|
||||||
Array<AnnotationArray*>* md = *md_p;
|
|
||||||
if (md != NULL && md->length() > idnum) {
|
|
||||||
md->at_put(idnum, anno);
|
|
||||||
} else if (anno != NULL) {
|
|
||||||
// create the array
|
|
||||||
int length = MAX2(idnum+1, (int)ik->idnum_allocated_count());
|
|
||||||
md = MetadataFactory::new_array<AnnotationArray*>(ik->class_loader_data(), length, CHECK);
|
|
||||||
if (*md_p != NULL) {
|
|
||||||
// copy the existing entries
|
|
||||||
for (int index = 0; index < (*md_p)->length(); index++) {
|
|
||||||
md->at_put(index, (*md_p)->at(index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set_annotations(md, md_p);
|
|
||||||
md->at_put(idnum, anno);
|
|
||||||
} // if no array and idnum isn't included there is nothing to do
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep created annotations in a global growable array (should be hashtable)
|
|
||||||
// need to add, search, delete when class is unloaded.
|
|
||||||
// Does it need a lock? yes. This sucks.
|
|
||||||
|
|
||||||
// Copy annotations to JVM call or reflection to the java heap.
|
// Copy annotations to JVM call or reflection to the java heap.
|
||||||
|
// The alternative to creating this array and adding to Java heap pressure
|
||||||
|
// is to have a hashtable of the already created typeArrayOops
|
||||||
typeArrayOop Annotations::make_java_array(AnnotationArray* annotations, TRAPS) {
|
typeArrayOop Annotations::make_java_array(AnnotationArray* annotations, TRAPS) {
|
||||||
if (annotations != NULL) {
|
if (annotations != NULL) {
|
||||||
int length = annotations->length();
|
int length = annotations->length();
|
||||||
@ -132,28 +96,15 @@ julong Annotations::count_bytes(Array<AnnotationArray*>* p) {
|
|||||||
void Annotations::collect_statistics(KlassSizeStats *sz) const {
|
void Annotations::collect_statistics(KlassSizeStats *sz) const {
|
||||||
sz->_annotations_bytes = sz->count(this);
|
sz->_annotations_bytes = sz->count(this);
|
||||||
sz->_class_annotations_bytes = sz->count(class_annotations());
|
sz->_class_annotations_bytes = sz->count(class_annotations());
|
||||||
|
sz->_class_type_annotations_bytes = sz->count(class_type_annotations());
|
||||||
sz->_fields_annotations_bytes = count_bytes(fields_annotations());
|
sz->_fields_annotations_bytes = count_bytes(fields_annotations());
|
||||||
sz->_methods_annotations_bytes = count_bytes(methods_annotations());
|
sz->_fields_type_annotations_bytes = count_bytes(fields_type_annotations());
|
||||||
sz->_methods_parameter_annotations_bytes =
|
|
||||||
count_bytes(methods_parameter_annotations());
|
|
||||||
sz->_methods_default_annotations_bytes =
|
|
||||||
count_bytes(methods_default_annotations());
|
|
||||||
|
|
||||||
const Annotations* type_anno = type_annotations();
|
|
||||||
if (type_anno != NULL) {
|
|
||||||
sz->_type_annotations_bytes = sz->count(type_anno);
|
|
||||||
sz->_type_annotations_bytes += sz->count(type_anno->class_annotations());
|
|
||||||
sz->_type_annotations_bytes += count_bytes(type_anno->fields_annotations());
|
|
||||||
sz->_type_annotations_bytes += count_bytes(type_anno->methods_annotations());
|
|
||||||
}
|
|
||||||
|
|
||||||
sz->_annotations_bytes +=
|
sz->_annotations_bytes +=
|
||||||
sz->_class_annotations_bytes +
|
sz->_class_annotations_bytes +
|
||||||
|
sz->_class_type_annotations_bytes +
|
||||||
sz->_fields_annotations_bytes +
|
sz->_fields_annotations_bytes +
|
||||||
sz->_methods_annotations_bytes +
|
sz->_fields_type_annotations_bytes;
|
||||||
sz->_methods_parameter_annotations_bytes +
|
|
||||||
sz->_methods_default_annotations_bytes +
|
|
||||||
sz->_type_annotations_bytes;
|
|
||||||
|
|
||||||
sz->_ro_bytes += sz->_annotations_bytes;
|
sz->_ro_bytes += sz->_annotations_bytes;
|
||||||
}
|
}
|
||||||
@ -165,8 +116,7 @@ void Annotations::collect_statistics(KlassSizeStats *sz) const {
|
|||||||
void Annotations::print_on(outputStream* st) const {
|
void Annotations::print_on(outputStream* st) const {
|
||||||
st->print(BULLET"class_annotations "); class_annotations()->print_value_on(st);
|
st->print(BULLET"class_annotations "); class_annotations()->print_value_on(st);
|
||||||
st->print(BULLET"fields_annotations "); fields_annotations()->print_value_on(st);
|
st->print(BULLET"fields_annotations "); fields_annotations()->print_value_on(st);
|
||||||
st->print(BULLET"methods_annotations "); methods_annotations()->print_value_on(st);
|
st->print(BULLET"class_type_annotations "); class_type_annotations()->print_value_on(st);
|
||||||
st->print(BULLET"methods_parameter_annotations"); methods_parameter_annotations()->print_value_on(st);
|
st->print(BULLET"fields_type_annotations "); fields_type_annotations()->print_value_on(st);
|
||||||
st->print(BULLET"methods_default_annotations "); methods_default_annotations()->print_value_on(st);
|
|
||||||
}
|
}
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
@ -49,38 +49,15 @@ class Annotations: public MetaspaceObj {
|
|||||||
// Annotation objects (byte arrays) for fields, or null if no annotations.
|
// Annotation objects (byte arrays) for fields, or null if no annotations.
|
||||||
// Indices correspond to entries (not indices) in fields array.
|
// Indices correspond to entries (not indices) in fields array.
|
||||||
Array<AnnotationArray*>* _fields_annotations;
|
Array<AnnotationArray*>* _fields_annotations;
|
||||||
// Annotation objects (byte arrays) for methods, or null if no annotations.
|
|
||||||
// Index is the idnum, which is initially the same as the methods array index.
|
|
||||||
Array<AnnotationArray*>* _methods_annotations;
|
|
||||||
// Annotation objects (byte arrays) for methods' parameters, or null if no
|
|
||||||
// such annotations.
|
|
||||||
// Index is the idnum, which is initially the same as the methods array index.
|
|
||||||
Array<AnnotationArray*>* _methods_parameter_annotations;
|
|
||||||
// Annotation objects (byte arrays) for methods' default values, or null if no
|
|
||||||
// such annotations.
|
|
||||||
// Index is the idnum, which is initially the same as the methods array index.
|
|
||||||
Array<AnnotationArray*>* _methods_default_annotations;
|
|
||||||
// Type annotations for this class, or null if none.
|
// Type annotations for this class, or null if none.
|
||||||
Annotations* _type_annotations;
|
AnnotationArray* _class_type_annotations;
|
||||||
|
Array<AnnotationArray*>* _fields_type_annotations;
|
||||||
// Constructor where some some values are known to not be null
|
|
||||||
Annotations(Array<AnnotationArray*>* fa, Array<AnnotationArray*>* ma,
|
|
||||||
Array<AnnotationArray*>* mpa, Array<AnnotationArray*>* mda) :
|
|
||||||
_class_annotations(NULL),
|
|
||||||
_fields_annotations(fa),
|
|
||||||
_methods_annotations(ma),
|
|
||||||
_methods_parameter_annotations(mpa),
|
|
||||||
_methods_default_annotations(mda),
|
|
||||||
_type_annotations(NULL) {}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Allocate instance of this class
|
// Allocate instance of this class
|
||||||
static Annotations* allocate(ClassLoaderData* loader_data, TRAPS);
|
static Annotations* allocate(ClassLoaderData* loader_data, TRAPS);
|
||||||
static Annotations* allocate(ClassLoaderData* loader_data,
|
|
||||||
Array<AnnotationArray*>* fa,
|
static void free_contents(ClassLoaderData* loader_data, Array<AnnotationArray*>* p);
|
||||||
Array<AnnotationArray*>* ma,
|
|
||||||
Array<AnnotationArray*>* mpa,
|
|
||||||
Array<AnnotationArray*>* mda, TRAPS);
|
|
||||||
void deallocate_contents(ClassLoaderData* loader_data);
|
void deallocate_contents(ClassLoaderData* loader_data);
|
||||||
DEBUG_ONLY(bool on_stack() { return false; }) // for template
|
DEBUG_ONLY(bool on_stack() { return false; }) // for template
|
||||||
|
|
||||||
@ -93,61 +70,24 @@ class Annotations: public MetaspaceObj {
|
|||||||
// Constructor to initialize to null
|
// Constructor to initialize to null
|
||||||
Annotations() : _class_annotations(NULL),
|
Annotations() : _class_annotations(NULL),
|
||||||
_fields_annotations(NULL),
|
_fields_annotations(NULL),
|
||||||
_methods_annotations(NULL),
|
_class_type_annotations(NULL),
|
||||||
_methods_parameter_annotations(NULL),
|
_fields_type_annotations(NULL) {}
|
||||||
_methods_default_annotations(NULL),
|
|
||||||
_type_annotations(NULL) {}
|
|
||||||
|
|
||||||
AnnotationArray* class_annotations() const { return _class_annotations; }
|
AnnotationArray* class_annotations() const { return _class_annotations; }
|
||||||
Array<AnnotationArray*>* fields_annotations() const { return _fields_annotations; }
|
Array<AnnotationArray*>* fields_annotations() const { return _fields_annotations; }
|
||||||
Array<AnnotationArray*>* methods_annotations() const { return _methods_annotations; }
|
AnnotationArray* class_type_annotations() const { return _class_type_annotations; }
|
||||||
Array<AnnotationArray*>* methods_parameter_annotations() const { return _methods_parameter_annotations; }
|
Array<AnnotationArray*>* fields_type_annotations() const { return _fields_type_annotations; }
|
||||||
Array<AnnotationArray*>* methods_default_annotations() const { return _methods_default_annotations; }
|
|
||||||
Annotations* type_annotations() const { return _type_annotations; }
|
|
||||||
|
|
||||||
void set_class_annotations(AnnotationArray* md) { _class_annotations = md; }
|
void set_class_annotations(AnnotationArray* md) { _class_annotations = md; }
|
||||||
void set_fields_annotations(Array<AnnotationArray*>* md) { _fields_annotations = md; }
|
void set_fields_annotations(Array<AnnotationArray*>* md) { _fields_annotations = md; }
|
||||||
void set_methods_annotations(Array<AnnotationArray*>* md) { _methods_annotations = md; }
|
void set_class_type_annotations(AnnotationArray* cta) { _class_type_annotations = cta; }
|
||||||
void set_methods_parameter_annotations(Array<AnnotationArray*>* md) { _methods_parameter_annotations = md; }
|
void set_fields_type_annotations(Array<AnnotationArray*>* fta) { _fields_type_annotations = fta; }
|
||||||
void set_methods_default_annotations(Array<AnnotationArray*>* md) { _methods_default_annotations = md; }
|
|
||||||
void set_type_annotations(Annotations* annos) { _type_annotations = annos; }
|
|
||||||
|
|
||||||
// Redefine classes support
|
|
||||||
AnnotationArray* get_method_annotations_of(int idnum)
|
|
||||||
{ return get_method_annotations_from(idnum, _methods_annotations); }
|
|
||||||
|
|
||||||
AnnotationArray* get_method_parameter_annotations_of(int idnum)
|
|
||||||
{ return get_method_annotations_from(idnum, _methods_parameter_annotations); }
|
|
||||||
AnnotationArray* get_method_default_annotations_of(int idnum)
|
|
||||||
{ return get_method_annotations_from(idnum, _methods_default_annotations); }
|
|
||||||
|
|
||||||
|
|
||||||
void set_method_annotations_of(instanceKlassHandle ik,
|
|
||||||
int idnum, AnnotationArray* anno, TRAPS) {
|
|
||||||
set_methods_annotations_of(ik, idnum, anno, &_methods_annotations, THREAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_method_parameter_annotations_of(instanceKlassHandle ik,
|
|
||||||
int idnum, AnnotationArray* anno, TRAPS) {
|
|
||||||
set_methods_annotations_of(ik, idnum, anno, &_methods_parameter_annotations, THREAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_method_default_annotations_of(instanceKlassHandle ik,
|
|
||||||
int idnum, AnnotationArray* anno, TRAPS) {
|
|
||||||
set_methods_annotations_of(ik, idnum, anno, &_methods_default_annotations, THREAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Turn metadata annotations into a Java heap object (oop)
|
// Turn metadata annotations into a Java heap object (oop)
|
||||||
static typeArrayOop make_java_array(AnnotationArray* annotations, TRAPS);
|
static typeArrayOop make_java_array(AnnotationArray* annotations, TRAPS);
|
||||||
|
|
||||||
inline AnnotationArray* get_method_annotations_from(int idnum, Array<AnnotationArray*>* annos);
|
|
||||||
void set_annotations(Array<AnnotationArray*>* md, Array<AnnotationArray*>** md_p) { *md_p = md; }
|
|
||||||
|
|
||||||
bool is_klass() const { return false; }
|
bool is_klass() const { return false; }
|
||||||
private:
|
private:
|
||||||
void set_methods_annotations_of(instanceKlassHandle ik,
|
|
||||||
int idnum, AnnotationArray* anno,
|
|
||||||
Array<AnnotationArray*>** md_p, TRAPS);
|
|
||||||
static julong count_bytes(Array<AnnotationArray*>* p);
|
static julong count_bytes(Array<AnnotationArray*>* p);
|
||||||
public:
|
public:
|
||||||
const char* internal_name() const { return "{constant pool}"; }
|
const char* internal_name() const { return "{constant pool}"; }
|
||||||
@ -156,13 +96,4 @@ class Annotations: public MetaspaceObj {
|
|||||||
#endif
|
#endif
|
||||||
void print_value_on(outputStream* st) const;
|
void print_value_on(outputStream* st) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// For method with idnum get the method's Annotations
|
|
||||||
inline AnnotationArray* Annotations::get_method_annotations_from(int idnum, Array<AnnotationArray*>* annos) {
|
|
||||||
if (annos == NULL || annos->length() <= idnum) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return annos->at(idnum);
|
|
||||||
}
|
|
||||||
#endif // SHARE_VM_OOPS_ANNOTATIONS_HPP
|
#endif // SHARE_VM_OOPS_ANNOTATIONS_HPP
|
||||||
|
@ -36,51 +36,26 @@ const u2 ConstMethod::UNSET_IDNUM = 0xFFFF;
|
|||||||
|
|
||||||
ConstMethod* ConstMethod::allocate(ClassLoaderData* loader_data,
|
ConstMethod* ConstMethod::allocate(ClassLoaderData* loader_data,
|
||||||
int byte_code_size,
|
int byte_code_size,
|
||||||
int compressed_line_number_size,
|
InlineTableSizes* sizes,
|
||||||
int localvariable_table_length,
|
|
||||||
int exception_table_length,
|
|
||||||
int checked_exceptions_length,
|
|
||||||
int method_parameters_length,
|
|
||||||
u2 generic_signature_index,
|
|
||||||
MethodType method_type,
|
MethodType method_type,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
int size = ConstMethod::size(byte_code_size,
|
int size = ConstMethod::size(byte_code_size, sizes);
|
||||||
compressed_line_number_size,
|
|
||||||
localvariable_table_length,
|
|
||||||
exception_table_length,
|
|
||||||
checked_exceptions_length,
|
|
||||||
method_parameters_length,
|
|
||||||
generic_signature_index);
|
|
||||||
return new (loader_data, size, true, THREAD) ConstMethod(
|
return new (loader_data, size, true, THREAD) ConstMethod(
|
||||||
byte_code_size, compressed_line_number_size, localvariable_table_length,
|
byte_code_size, sizes, method_type, size);
|
||||||
exception_table_length, checked_exceptions_length,
|
|
||||||
method_parameters_length, generic_signature_index,
|
|
||||||
method_type, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstMethod::ConstMethod(int byte_code_size,
|
ConstMethod::ConstMethod(int byte_code_size,
|
||||||
int compressed_line_number_size,
|
InlineTableSizes* sizes,
|
||||||
int localvariable_table_length,
|
|
||||||
int exception_table_length,
|
|
||||||
int checked_exceptions_length,
|
|
||||||
int method_parameters_length,
|
|
||||||
u2 generic_signature_index,
|
|
||||||
MethodType method_type,
|
MethodType method_type,
|
||||||
int size) {
|
int size) {
|
||||||
|
|
||||||
No_Safepoint_Verifier no_safepoint;
|
No_Safepoint_Verifier no_safepoint;
|
||||||
set_interpreter_kind(Interpreter::invalid);
|
|
||||||
init_fingerprint();
|
init_fingerprint();
|
||||||
set_constants(NULL);
|
set_constants(NULL);
|
||||||
set_stackmap_data(NULL);
|
set_stackmap_data(NULL);
|
||||||
set_code_size(byte_code_size);
|
set_code_size(byte_code_size);
|
||||||
set_constMethod_size(size);
|
set_constMethod_size(size);
|
||||||
set_inlined_tables_length(generic_signature_index,
|
set_inlined_tables_length(sizes);
|
||||||
checked_exceptions_length,
|
|
||||||
compressed_line_number_size,
|
|
||||||
localvariable_table_length,
|
|
||||||
exception_table_length,
|
|
||||||
method_parameters_length);
|
|
||||||
set_method_type(method_type);
|
set_method_type(method_type);
|
||||||
assert(this->size() == size, "wrong size for object");
|
assert(this->size() == size, "wrong size for object");
|
||||||
}
|
}
|
||||||
@ -88,47 +63,70 @@ ConstMethod::ConstMethod(int byte_code_size,
|
|||||||
|
|
||||||
// Deallocate metadata fields associated with ConstMethod*
|
// Deallocate metadata fields associated with ConstMethod*
|
||||||
void ConstMethod::deallocate_contents(ClassLoaderData* loader_data) {
|
void ConstMethod::deallocate_contents(ClassLoaderData* loader_data) {
|
||||||
set_interpreter_kind(Interpreter::invalid);
|
|
||||||
if (stackmap_data() != NULL) {
|
if (stackmap_data() != NULL) {
|
||||||
MetadataFactory::free_array<u1>(loader_data, stackmap_data());
|
MetadataFactory::free_array<u1>(loader_data, stackmap_data());
|
||||||
}
|
}
|
||||||
set_stackmap_data(NULL);
|
set_stackmap_data(NULL);
|
||||||
|
|
||||||
|
// deallocate annotation arrays
|
||||||
|
if (has_method_annotations())
|
||||||
|
MetadataFactory::free_array<u1>(loader_data, method_annotations());
|
||||||
|
if (has_parameter_annotations())
|
||||||
|
MetadataFactory::free_array<u1>(loader_data, parameter_annotations());
|
||||||
|
if (has_type_annotations())
|
||||||
|
MetadataFactory::free_array<u1>(loader_data, type_annotations());
|
||||||
|
if (has_default_annotations())
|
||||||
|
MetadataFactory::free_array<u1>(loader_data, default_annotations());
|
||||||
}
|
}
|
||||||
|
|
||||||
// How big must this constMethodObject be?
|
// How big must this constMethodObject be?
|
||||||
|
|
||||||
int ConstMethod::size(int code_size,
|
int ConstMethod::size(int code_size,
|
||||||
int compressed_line_number_size,
|
InlineTableSizes* sizes) {
|
||||||
int local_variable_table_length,
|
|
||||||
int exception_table_length,
|
|
||||||
int checked_exceptions_length,
|
|
||||||
int method_parameters_length,
|
|
||||||
u2 generic_signature_index) {
|
|
||||||
int extra_bytes = code_size;
|
int extra_bytes = code_size;
|
||||||
if (compressed_line_number_size > 0) {
|
if (sizes->compressed_linenumber_size() > 0) {
|
||||||
extra_bytes += compressed_line_number_size;
|
extra_bytes += sizes->compressed_linenumber_size();
|
||||||
}
|
}
|
||||||
if (checked_exceptions_length > 0) {
|
if (sizes->checked_exceptions_length() > 0) {
|
||||||
extra_bytes += sizeof(u2);
|
extra_bytes += sizeof(u2);
|
||||||
extra_bytes += checked_exceptions_length * sizeof(CheckedExceptionElement);
|
extra_bytes += sizes->checked_exceptions_length() * sizeof(CheckedExceptionElement);
|
||||||
}
|
}
|
||||||
if (local_variable_table_length > 0) {
|
if (sizes->localvariable_table_length() > 0) {
|
||||||
extra_bytes += sizeof(u2);
|
extra_bytes += sizeof(u2);
|
||||||
extra_bytes +=
|
extra_bytes +=
|
||||||
local_variable_table_length * sizeof(LocalVariableTableElement);
|
sizes->localvariable_table_length() * sizeof(LocalVariableTableElement);
|
||||||
}
|
}
|
||||||
if (exception_table_length > 0) {
|
if (sizes->exception_table_length() > 0) {
|
||||||
extra_bytes += sizeof(u2);
|
extra_bytes += sizeof(u2);
|
||||||
extra_bytes += exception_table_length * sizeof(ExceptionTableElement);
|
extra_bytes += sizes->exception_table_length() * sizeof(ExceptionTableElement);
|
||||||
}
|
}
|
||||||
if (generic_signature_index != 0) {
|
if (sizes->generic_signature_index() != 0) {
|
||||||
extra_bytes += sizeof(u2);
|
extra_bytes += sizeof(u2);
|
||||||
}
|
}
|
||||||
if (method_parameters_length > 0) {
|
if (sizes->method_parameters_length() > 0) {
|
||||||
extra_bytes += sizeof(u2);
|
extra_bytes += sizeof(u2);
|
||||||
extra_bytes += method_parameters_length * sizeof(MethodParametersElement);
|
extra_bytes += sizes->method_parameters_length() * sizeof(MethodParametersElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Align sizes up to a word.
|
||||||
|
extra_bytes = align_size_up(extra_bytes, BytesPerWord);
|
||||||
|
|
||||||
|
// One pointer per annotation array
|
||||||
|
if (sizes->method_annotations_length() > 0) {
|
||||||
|
extra_bytes += sizeof(AnnotationArray*);
|
||||||
|
}
|
||||||
|
if (sizes->parameter_annotations_length() > 0) {
|
||||||
|
extra_bytes += sizeof(AnnotationArray*);
|
||||||
|
}
|
||||||
|
if (sizes->type_annotations_length() > 0) {
|
||||||
|
extra_bytes += sizeof(AnnotationArray*);
|
||||||
|
}
|
||||||
|
if (sizes->default_annotations_length() > 0) {
|
||||||
|
extra_bytes += sizeof(AnnotationArray*);
|
||||||
|
}
|
||||||
|
|
||||||
int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord;
|
int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord;
|
||||||
|
assert(extra_words == extra_bytes/BytesPerWord, "should already be aligned");
|
||||||
return align_object_size(header_size() + extra_words);
|
return align_object_size(header_size() + extra_words);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,12 +143,28 @@ u_char* ConstMethod::compressed_linenumber_table() const {
|
|||||||
return code_end();
|
return code_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Last short in ConstMethod* before annotations
|
||||||
|
u2* ConstMethod::last_u2_element() const {
|
||||||
|
int offset = 0;
|
||||||
|
if (has_method_annotations()) offset++;
|
||||||
|
if (has_parameter_annotations()) offset++;
|
||||||
|
if (has_type_annotations()) offset++;
|
||||||
|
if (has_default_annotations()) offset++;
|
||||||
|
return (u2*)((AnnotationArray**)constMethod_end() - offset) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
u2* ConstMethod::generic_signature_index_addr() const {
|
u2* ConstMethod::generic_signature_index_addr() const {
|
||||||
// Located at the end of the constMethod.
|
// Located at the end of the constMethod.
|
||||||
assert(has_generic_signature(), "called only if generic signature exists");
|
assert(has_generic_signature(), "called only if generic signature exists");
|
||||||
return last_u2_element();
|
return last_u2_element();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u2* ConstMethod::method_parameters_length_addr() const {
|
||||||
|
assert(has_method_parameters(), "called only if table is present");
|
||||||
|
return has_generic_signature() ? (last_u2_element() - 1) :
|
||||||
|
last_u2_element();
|
||||||
|
}
|
||||||
|
|
||||||
u2* ConstMethod::checked_exceptions_length_addr() const {
|
u2* ConstMethod::checked_exceptions_length_addr() const {
|
||||||
// Located immediately before the generic signature index.
|
// Located immediately before the generic signature index.
|
||||||
assert(has_checked_exceptions(), "called only if table is present");
|
assert(has_checked_exceptions(), "called only if table is present");
|
||||||
@ -164,12 +178,6 @@ u2* ConstMethod::checked_exceptions_length_addr() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u2* ConstMethod::method_parameters_length_addr() const {
|
|
||||||
assert(has_method_parameters(), "called only if table is present");
|
|
||||||
return has_generic_signature() ? (last_u2_element() - 1) :
|
|
||||||
last_u2_element();
|
|
||||||
}
|
|
||||||
|
|
||||||
u2* ConstMethod::exception_table_length_addr() const {
|
u2* ConstMethod::exception_table_length_addr() const {
|
||||||
assert(has_exception_handler(), "called only if table is present");
|
assert(has_exception_handler(), "called only if table is present");
|
||||||
if (has_checked_exceptions()) {
|
if (has_checked_exceptions()) {
|
||||||
@ -181,9 +189,9 @@ u2* ConstMethod::exception_table_length_addr() const {
|
|||||||
return (u2*)method_parameters_start() - 1;
|
return (u2*)method_parameters_start() - 1;
|
||||||
} else {
|
} else {
|
||||||
// Else, the exception table is at the end of the constMethod.
|
// Else, the exception table is at the end of the constMethod.
|
||||||
return has_generic_signature() ? (last_u2_element() - 1) :
|
return has_generic_signature() ? (last_u2_element() - 1) :
|
||||||
last_u2_element();
|
last_u2_element();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,32 +212,38 @@ u2* ConstMethod::localvariable_table_length_addr() const {
|
|||||||
// Else, the exception table is at the end of the constMethod.
|
// Else, the exception table is at the end of the constMethod.
|
||||||
return has_generic_signature() ? (last_u2_element() - 1) :
|
return has_generic_signature() ? (last_u2_element() - 1) :
|
||||||
last_u2_element();
|
last_u2_element();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the flags to indicate the presence of these optional fields.
|
// Update the flags to indicate the presence of these optional fields.
|
||||||
void ConstMethod::set_inlined_tables_length(u2 generic_signature_index,
|
void ConstMethod::set_inlined_tables_length(InlineTableSizes* sizes) {
|
||||||
int checked_exceptions_len,
|
_flags = 0;
|
||||||
int compressed_line_number_size,
|
if (sizes->compressed_linenumber_size() > 0)
|
||||||
int localvariable_table_len,
|
|
||||||
int exception_table_len,
|
|
||||||
int method_parameters_len) {
|
|
||||||
assert(_flags == 0, "Error");
|
|
||||||
if (compressed_line_number_size > 0)
|
|
||||||
_flags |= _has_linenumber_table;
|
_flags |= _has_linenumber_table;
|
||||||
if (generic_signature_index != 0)
|
if (sizes->generic_signature_index() != 0)
|
||||||
_flags |= _has_generic_signature;
|
_flags |= _has_generic_signature;
|
||||||
if (method_parameters_len > 0)
|
if (sizes->method_parameters_length() > 0)
|
||||||
_flags |= _has_method_parameters;
|
_flags |= _has_method_parameters;
|
||||||
if (checked_exceptions_len > 0)
|
if (sizes->checked_exceptions_length() > 0)
|
||||||
_flags |= _has_checked_exceptions;
|
_flags |= _has_checked_exceptions;
|
||||||
if (exception_table_len > 0)
|
if (sizes->exception_table_length() > 0)
|
||||||
_flags |= _has_exception_table;
|
_flags |= _has_exception_table;
|
||||||
if (localvariable_table_len > 0)
|
if (sizes->localvariable_table_length() > 0)
|
||||||
_flags |= _has_localvariable_table;
|
_flags |= _has_localvariable_table;
|
||||||
|
|
||||||
|
// annotations, they are all pointer sized embedded objects so don't have
|
||||||
|
// a length embedded also.
|
||||||
|
if (sizes->method_annotations_length() > 0)
|
||||||
|
_flags |= _has_method_annotations;
|
||||||
|
if (sizes->parameter_annotations_length() > 0)
|
||||||
|
_flags |= _has_parameter_annotations;
|
||||||
|
if (sizes->type_annotations_length() > 0)
|
||||||
|
_flags |= _has_type_annotations;
|
||||||
|
if (sizes->default_annotations_length() > 0)
|
||||||
|
_flags |= _has_default_annotations;
|
||||||
|
|
||||||
// This code is extremely brittle and should possibly be revised.
|
// This code is extremely brittle and should possibly be revised.
|
||||||
// The *_length_addr functions walk backwards through the
|
// The *_length_addr functions walk backwards through the
|
||||||
// constMethod data, using each of the length indexes ahead of them,
|
// constMethod data, using each of the length indexes ahead of them,
|
||||||
@ -242,17 +256,17 @@ void ConstMethod::set_inlined_tables_length(u2 generic_signature_index,
|
|||||||
// Also, the servicability agent needs to be informed anytime
|
// Also, the servicability agent needs to be informed anytime
|
||||||
// anything is added here. It might be advisable to have some sort
|
// anything is added here. It might be advisable to have some sort
|
||||||
// of indication of this inline.
|
// of indication of this inline.
|
||||||
if (generic_signature_index != 0)
|
if (sizes->generic_signature_index() != 0)
|
||||||
*(generic_signature_index_addr()) = generic_signature_index;
|
*(generic_signature_index_addr()) = sizes->generic_signature_index();
|
||||||
// New data should probably go here.
|
// New data should probably go here.
|
||||||
if (method_parameters_len > 0)
|
if (sizes->method_parameters_length() > 0)
|
||||||
*(method_parameters_length_addr()) = method_parameters_len;
|
*(method_parameters_length_addr()) = sizes->method_parameters_length();
|
||||||
if (checked_exceptions_len > 0)
|
if (sizes->checked_exceptions_length() > 0)
|
||||||
*(checked_exceptions_length_addr()) = checked_exceptions_len;
|
*(checked_exceptions_length_addr()) = sizes->checked_exceptions_length();
|
||||||
if (exception_table_len > 0)
|
if (sizes->exception_table_length() > 0)
|
||||||
*(exception_table_length_addr()) = exception_table_len;
|
*(exception_table_length_addr()) = sizes->exception_table_length();
|
||||||
if (localvariable_table_len > 0)
|
if (sizes->localvariable_table_length() > 0)
|
||||||
*(localvariable_table_length_addr()) = localvariable_table_len;
|
*(localvariable_table_length_addr()) = sizes->localvariable_table_length();
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConstMethod::method_parameters_length() const {
|
int ConstMethod::method_parameters_length() const {
|
||||||
@ -307,6 +321,34 @@ ExceptionTableElement* ConstMethod::exception_table_start() const {
|
|||||||
return (ExceptionTableElement*)addr;
|
return (ExceptionTableElement*)addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AnnotationArray** ConstMethod::method_annotations_addr() const {
|
||||||
|
assert(has_method_annotations(), "should only be called if method annotations are present");
|
||||||
|
return (AnnotationArray**)constMethod_end() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnotationArray** ConstMethod::parameter_annotations_addr() const {
|
||||||
|
assert(has_parameter_annotations(), "should only be called if method parameter annotations are present");
|
||||||
|
int offset = 1;
|
||||||
|
if (has_method_annotations()) offset++;
|
||||||
|
return (AnnotationArray**)constMethod_end() - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnotationArray** ConstMethod::type_annotations_addr() const {
|
||||||
|
assert(has_type_annotations(), "should only be called if method type annotations are present");
|
||||||
|
int offset = 1;
|
||||||
|
if (has_method_annotations()) offset++;
|
||||||
|
if (has_parameter_annotations()) offset++;
|
||||||
|
return (AnnotationArray**)constMethod_end() - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnotationArray** ConstMethod::default_annotations_addr() const {
|
||||||
|
assert(has_default_annotations(), "should only be called if method default annotations are present");
|
||||||
|
int offset = 1;
|
||||||
|
if (has_method_annotations()) offset++;
|
||||||
|
if (has_parameter_annotations()) offset++;
|
||||||
|
if (has_type_annotations()) offset++;
|
||||||
|
return (AnnotationArray**)constMethod_end() - offset;
|
||||||
|
}
|
||||||
|
|
||||||
// Printing
|
// Printing
|
||||||
|
|
||||||
@ -339,8 +381,25 @@ void ConstMethod::collect_statistics(KlassSizeStats *sz) const {
|
|||||||
sz->_bytecode_bytes += (n2 = code_size());
|
sz->_bytecode_bytes += (n2 = code_size());
|
||||||
sz->_stackmap_bytes += (n3 = sz->count_array(stackmap_data()));
|
sz->_stackmap_bytes += (n3 = sz->count_array(stackmap_data()));
|
||||||
|
|
||||||
sz->_method_all_bytes += n1 + n3; // note: n2 is part of n3
|
// Count method annotations
|
||||||
sz->_ro_bytes += n1 + n3;
|
int a1 = 0, a2 = 0, a3 = 0, a4 = 0;
|
||||||
|
if (has_method_annotations()) {
|
||||||
|
sz->_methods_annotations_bytes += (a1 = sz->count_array(method_annotations()));
|
||||||
|
}
|
||||||
|
if (has_parameter_annotations()) {
|
||||||
|
sz->_methods_parameter_annotations_bytes += (a2 = sz->count_array(parameter_annotations()));
|
||||||
|
}
|
||||||
|
if (has_type_annotations()) {
|
||||||
|
sz->_methods_type_annotations_bytes += (a3 = sz->count_array(type_annotations()));
|
||||||
|
}
|
||||||
|
if (has_default_annotations()) {
|
||||||
|
sz->_methods_default_annotations_bytes += (a4 = sz->count_array(default_annotations()));
|
||||||
|
}
|
||||||
|
|
||||||
|
int size_annotations = a1 + a2 + a3 + a4;
|
||||||
|
|
||||||
|
sz->_method_all_bytes += n1 + n3 + size_annotations; // note: n2 is part of n3
|
||||||
|
sz->_ro_bytes += n1 + n3 + size_annotations;
|
||||||
}
|
}
|
||||||
#endif // INCLUDE_SERVICES
|
#endif // INCLUDE_SERVICES
|
||||||
|
|
||||||
@ -352,10 +411,9 @@ void ConstMethod::verify_on(outputStream* st) {
|
|||||||
|
|
||||||
// Verification can occur during oop construction before the method or
|
// Verification can occur during oop construction before the method or
|
||||||
// other fields have been initialized.
|
// other fields have been initialized.
|
||||||
guarantee(is_metadata(), err_msg("Should be metadata " PTR_FORMAT, this));
|
|
||||||
guarantee(method()->is_method(), "should be method");
|
guarantee(method()->is_method(), "should be method");
|
||||||
|
|
||||||
address m_end = (address)((oop*) this + size());
|
address m_end = (address)((intptr_t) this + size());
|
||||||
address compressed_table_start = code_end();
|
address compressed_table_start = code_end();
|
||||||
guarantee(compressed_table_start <= m_end, "invalid method layout");
|
guarantee(compressed_table_start <= m_end, "invalid method layout");
|
||||||
address compressed_table_end = compressed_table_start;
|
address compressed_table_end = compressed_table_start;
|
||||||
|
@ -86,19 +86,22 @@
|
|||||||
// | generic signature index (u2) |
|
// | generic signature index (u2) |
|
||||||
// | (indexed from start of constMethodOop) |
|
// | (indexed from start of constMethodOop) |
|
||||||
// |------------------------------------------------------|
|
// |------------------------------------------------------|
|
||||||
|
// | annotations arrays - method, parameter, type, default|
|
||||||
|
// | pointer to Array<u1> if annotation is present |
|
||||||
|
// |------------------------------------------------------|
|
||||||
//
|
//
|
||||||
// IMPORTANT: If anything gets added here, there need to be changes to
|
// IMPORTANT: If anything gets added here, there need to be changes to
|
||||||
// ensure that ServicabilityAgent doesn't get broken as a result!
|
// ensure that ServicabilityAgent doesn't get broken as a result!
|
||||||
|
|
||||||
|
|
||||||
// Utitily class decribing elements in checked exceptions table inlined in Method*.
|
// Utility class describing elements in checked exceptions table inlined in Method*.
|
||||||
class CheckedExceptionElement VALUE_OBJ_CLASS_SPEC {
|
class CheckedExceptionElement VALUE_OBJ_CLASS_SPEC {
|
||||||
public:
|
public:
|
||||||
u2 class_cp_index;
|
u2 class_cp_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Utitily class decribing elements in local variable table inlined in Method*.
|
// Utility class describing elements in local variable table inlined in Method*.
|
||||||
class LocalVariableTableElement VALUE_OBJ_CLASS_SPEC {
|
class LocalVariableTableElement VALUE_OBJ_CLASS_SPEC {
|
||||||
public:
|
public:
|
||||||
u2 start_bci;
|
u2 start_bci;
|
||||||
@ -109,7 +112,7 @@ class LocalVariableTableElement VALUE_OBJ_CLASS_SPEC {
|
|||||||
u2 slot;
|
u2 slot;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Utitily class describing elements in exception table
|
// Utility class describing elements in exception table
|
||||||
class ExceptionTableElement VALUE_OBJ_CLASS_SPEC {
|
class ExceptionTableElement VALUE_OBJ_CLASS_SPEC {
|
||||||
public:
|
public:
|
||||||
u2 start_pc;
|
u2 start_pc;
|
||||||
@ -127,6 +130,51 @@ class MethodParametersElement VALUE_OBJ_CLASS_SPEC {
|
|||||||
|
|
||||||
class KlassSizeStats;
|
class KlassSizeStats;
|
||||||
|
|
||||||
|
// Class to collect the sizes of ConstMethod inline tables
|
||||||
|
#define INLINE_TABLES_DO(do_element) \
|
||||||
|
do_element(localvariable_table_length) \
|
||||||
|
do_element(compressed_linenumber_size) \
|
||||||
|
do_element(exception_table_length) \
|
||||||
|
do_element(checked_exceptions_length) \
|
||||||
|
do_element(method_parameters_length) \
|
||||||
|
do_element(generic_signature_index) \
|
||||||
|
do_element(method_annotations_length) \
|
||||||
|
do_element(parameter_annotations_length) \
|
||||||
|
do_element(type_annotations_length) \
|
||||||
|
do_element(default_annotations_length)
|
||||||
|
|
||||||
|
#define INLINE_TABLE_DECLARE(sym) int _##sym;
|
||||||
|
#define INLINE_TABLE_PARAM(sym) int sym,
|
||||||
|
#define INLINE_TABLE_INIT(sym) _##sym(sym),
|
||||||
|
#define INLINE_TABLE_NULL(sym) _##sym(0),
|
||||||
|
#define INLINE_TABLE_ACCESSOR(sym) int sym() const { return _##sym; }
|
||||||
|
|
||||||
|
class InlineTableSizes : StackObj {
|
||||||
|
// declarations
|
||||||
|
INLINE_TABLES_DO(INLINE_TABLE_DECLARE)
|
||||||
|
int _end;
|
||||||
|
public:
|
||||||
|
InlineTableSizes(
|
||||||
|
INLINE_TABLES_DO(INLINE_TABLE_PARAM)
|
||||||
|
int end) :
|
||||||
|
INLINE_TABLES_DO(INLINE_TABLE_INIT)
|
||||||
|
_end(end) {}
|
||||||
|
|
||||||
|
// Default constructor for no inlined tables
|
||||||
|
InlineTableSizes() :
|
||||||
|
INLINE_TABLES_DO(INLINE_TABLE_NULL)
|
||||||
|
_end(0) {}
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
INLINE_TABLES_DO(INLINE_TABLE_ACCESSOR)
|
||||||
|
};
|
||||||
|
#undef INLINE_TABLE_ACCESSOR
|
||||||
|
#undef INLINE_TABLE_NULL
|
||||||
|
#undef INLINE_TABLE_INIT
|
||||||
|
#undef INLINE_TABLE_PARAM
|
||||||
|
#undef INLINE_TABLE_DECLARE
|
||||||
|
|
||||||
|
|
||||||
class ConstMethod : public MetaspaceObj {
|
class ConstMethod : public MetaspaceObj {
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
|
|
||||||
@ -135,13 +183,17 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
_has_linenumber_table = 1,
|
_has_linenumber_table = 0x0001,
|
||||||
_has_checked_exceptions = 2,
|
_has_checked_exceptions = 0x0002,
|
||||||
_has_localvariable_table = 4,
|
_has_localvariable_table = 0x0004,
|
||||||
_has_exception_table = 8,
|
_has_exception_table = 0x0008,
|
||||||
_has_generic_signature = 16,
|
_has_generic_signature = 0x0010,
|
||||||
_has_method_parameters = 32,
|
_has_method_parameters = 0x0020,
|
||||||
_is_overpass = 64
|
_is_overpass = 0x0040,
|
||||||
|
_has_method_annotations = 0x0080,
|
||||||
|
_has_parameter_annotations = 0x0100,
|
||||||
|
_has_type_annotations = 0x0200,
|
||||||
|
_has_default_annotations = 0x0400
|
||||||
};
|
};
|
||||||
|
|
||||||
// Bit vector of signature
|
// Bit vector of signature
|
||||||
@ -158,8 +210,7 @@ private:
|
|||||||
Array<u1>* _stackmap_data;
|
Array<u1>* _stackmap_data;
|
||||||
|
|
||||||
int _constMethod_size;
|
int _constMethod_size;
|
||||||
jbyte _interpreter_kind;
|
u2 _flags;
|
||||||
jbyte _flags;
|
|
||||||
|
|
||||||
// Size of Java bytecodes allocated immediately after Method*.
|
// Size of Java bytecodes allocated immediately after Method*.
|
||||||
u2 _code_size;
|
u2 _code_size;
|
||||||
@ -174,36 +225,21 @@ private:
|
|||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
ConstMethod(int byte_code_size,
|
ConstMethod(int byte_code_size,
|
||||||
int compressed_line_number_size,
|
InlineTableSizes* sizes,
|
||||||
int localvariable_table_length,
|
|
||||||
int exception_table_length,
|
|
||||||
int checked_exceptions_length,
|
|
||||||
int method_parameters_length,
|
|
||||||
u2 generic_signature_index,
|
|
||||||
MethodType is_overpass,
|
MethodType is_overpass,
|
||||||
int size);
|
int size);
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static ConstMethod* allocate(ClassLoaderData* loader_data,
|
static ConstMethod* allocate(ClassLoaderData* loader_data,
|
||||||
int byte_code_size,
|
int byte_code_size,
|
||||||
int compressed_line_number_size,
|
InlineTableSizes* sizes,
|
||||||
int localvariable_table_length,
|
|
||||||
int exception_table_length,
|
|
||||||
int checked_exceptions_length,
|
|
||||||
int method_parameters_length,
|
|
||||||
u2 generic_signature_index,
|
|
||||||
MethodType mt,
|
MethodType mt,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
|
|
||||||
bool is_constMethod() const { return true; }
|
bool is_constMethod() const { return true; }
|
||||||
|
|
||||||
// Inlined tables
|
// Inlined tables
|
||||||
void set_inlined_tables_length(u2 generic_signature_index,
|
void set_inlined_tables_length(InlineTableSizes* sizes);
|
||||||
int checked_exceptions_len,
|
|
||||||
int compressed_line_number_size,
|
|
||||||
int localvariable_table_len,
|
|
||||||
int exception_table_len,
|
|
||||||
int method_parameters_length);
|
|
||||||
|
|
||||||
bool has_generic_signature() const
|
bool has_generic_signature() const
|
||||||
{ return (_flags & _has_generic_signature) != 0; }
|
{ return (_flags & _has_generic_signature) != 0; }
|
||||||
@ -235,10 +271,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void set_interpreter_kind(int kind) { _interpreter_kind = kind; }
|
|
||||||
int interpreter_kind(void) const { return _interpreter_kind; }
|
|
||||||
|
|
||||||
// constant pool
|
// constant pool
|
||||||
ConstantPool* constants() const { return _constants; }
|
ConstantPool* constants() const { return _constants; }
|
||||||
void set_constants(ConstantPool* c) { _constants = c; }
|
void set_constants(ConstantPool* c) { _constants = c; }
|
||||||
@ -307,12 +339,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Size needed
|
// Size needed
|
||||||
static int size(int code_size, int compressed_line_number_size,
|
static int size(int code_size, InlineTableSizes* sizes);
|
||||||
int local_variable_table_length,
|
|
||||||
int exception_table_length,
|
|
||||||
int checked_exceptions_length,
|
|
||||||
int method_parameters_length,
|
|
||||||
u2 generic_signature_index);
|
|
||||||
|
|
||||||
int size() const { return _constMethod_size;}
|
int size() const { return _constMethod_size;}
|
||||||
void set_constMethod_size(int size) { _constMethod_size = size; }
|
void set_constMethod_size(int size) { _constMethod_size = size; }
|
||||||
@ -354,6 +381,65 @@ public:
|
|||||||
int method_parameters_length() const;
|
int method_parameters_length() const;
|
||||||
MethodParametersElement* method_parameters_start() const;
|
MethodParametersElement* method_parameters_start() const;
|
||||||
|
|
||||||
|
// method annotations
|
||||||
|
bool has_method_annotations() const
|
||||||
|
{ return (_flags & _has_method_annotations) != 0; }
|
||||||
|
|
||||||
|
bool has_parameter_annotations() const
|
||||||
|
{ return (_flags & _has_parameter_annotations) != 0; }
|
||||||
|
|
||||||
|
bool has_type_annotations() const
|
||||||
|
{ return (_flags & _has_type_annotations) != 0; }
|
||||||
|
|
||||||
|
bool has_default_annotations() const
|
||||||
|
{ return (_flags & _has_default_annotations) != 0; }
|
||||||
|
|
||||||
|
|
||||||
|
AnnotationArray** method_annotations_addr() const;
|
||||||
|
AnnotationArray* method_annotations() const {
|
||||||
|
return has_method_annotations() ? *(method_annotations_addr()) : NULL;
|
||||||
|
}
|
||||||
|
void set_method_annotations(AnnotationArray* anno) {
|
||||||
|
*(method_annotations_addr()) = anno;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnotationArray** parameter_annotations_addr() const;
|
||||||
|
AnnotationArray* parameter_annotations() const {
|
||||||
|
return has_parameter_annotations() ? *(parameter_annotations_addr()) : NULL;
|
||||||
|
}
|
||||||
|
void set_parameter_annotations(AnnotationArray* anno) {
|
||||||
|
*(parameter_annotations_addr()) = anno;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnotationArray** type_annotations_addr() const;
|
||||||
|
AnnotationArray* type_annotations() const {
|
||||||
|
return has_type_annotations() ? *(type_annotations_addr()) : NULL;
|
||||||
|
}
|
||||||
|
void set_type_annotations(AnnotationArray* anno) {
|
||||||
|
*(type_annotations_addr()) = anno;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnotationArray** default_annotations_addr() const;
|
||||||
|
AnnotationArray* default_annotations() const {
|
||||||
|
return has_default_annotations() ? *(default_annotations_addr()) : NULL;
|
||||||
|
}
|
||||||
|
void set_default_annotations(AnnotationArray* anno) {
|
||||||
|
*(default_annotations_addr()) = anno;
|
||||||
|
}
|
||||||
|
|
||||||
|
int method_annotations_length() const {
|
||||||
|
return has_method_annotations() ? method_annotations()->length() : 0;
|
||||||
|
}
|
||||||
|
int parameter_annotations_length() const {
|
||||||
|
return has_parameter_annotations() ? parameter_annotations()->length() : 0;
|
||||||
|
}
|
||||||
|
int type_annotations_length() const {
|
||||||
|
return has_type_annotations() ? type_annotations()->length() : 0;
|
||||||
|
}
|
||||||
|
int default_annotations_length() const {
|
||||||
|
return has_default_annotations() ? default_annotations()->length() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
// byte codes
|
// byte codes
|
||||||
void set_code(address code) {
|
void set_code(address code) {
|
||||||
if (code_size() > 0) {
|
if (code_size() > 0) {
|
||||||
@ -409,11 +495,10 @@ private:
|
|||||||
|
|
||||||
// First byte after ConstMethod*
|
// First byte after ConstMethod*
|
||||||
address constMethod_end() const
|
address constMethod_end() const
|
||||||
{ return (address)((oop*)this + _constMethod_size); }
|
{ return (address)((intptr_t*)this + _constMethod_size); }
|
||||||
|
|
||||||
// Last short in ConstMethod*
|
// Last short in ConstMethod*
|
||||||
u2* last_u2_element() const
|
u2* last_u2_element() const;
|
||||||
{ return (u2*)constMethod_end() - 1; }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Printing
|
// Printing
|
||||||
|
@ -166,20 +166,19 @@ HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end,
|
|||||||
volatile int InstanceKlass::_total_instanceKlass_count = 0;
|
volatile int InstanceKlass::_total_instanceKlass_count = 0;
|
||||||
|
|
||||||
Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data,
|
Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data,
|
||||||
int vtable_len,
|
int vtable_len,
|
||||||
int itable_len,
|
int itable_len,
|
||||||
int static_field_size,
|
int static_field_size,
|
||||||
int nonstatic_oop_map_size,
|
int nonstatic_oop_map_size,
|
||||||
ReferenceType rt,
|
ReferenceType rt,
|
||||||
AccessFlags access_flags,
|
AccessFlags access_flags,
|
||||||
Symbol* name,
|
Symbol* name,
|
||||||
Klass* super_klass,
|
Klass* super_klass,
|
||||||
KlassHandle host_klass,
|
bool is_anonymous,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
|
|
||||||
int size = InstanceKlass::size(vtable_len, itable_len, nonstatic_oop_map_size,
|
int size = InstanceKlass::size(vtable_len, itable_len, nonstatic_oop_map_size,
|
||||||
access_flags.is_interface(),
|
access_flags.is_interface(), is_anonymous);
|
||||||
!host_klass.is_null());
|
|
||||||
|
|
||||||
// Allocation
|
// Allocation
|
||||||
InstanceKlass* ik;
|
InstanceKlass* ik;
|
||||||
@ -187,25 +186,25 @@ Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data,
|
|||||||
if (name == vmSymbols::java_lang_Class()) {
|
if (name == vmSymbols::java_lang_Class()) {
|
||||||
ik = new (loader_data, size, THREAD) InstanceMirrorKlass(
|
ik = new (loader_data, size, THREAD) InstanceMirrorKlass(
|
||||||
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
|
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
|
||||||
access_flags, !host_klass.is_null());
|
access_flags, is_anonymous);
|
||||||
} else if (name == vmSymbols::java_lang_ClassLoader() ||
|
} else if (name == vmSymbols::java_lang_ClassLoader() ||
|
||||||
(SystemDictionary::ClassLoader_klass_loaded() &&
|
(SystemDictionary::ClassLoader_klass_loaded() &&
|
||||||
super_klass != NULL &&
|
super_klass != NULL &&
|
||||||
super_klass->is_subtype_of(SystemDictionary::ClassLoader_klass()))) {
|
super_klass->is_subtype_of(SystemDictionary::ClassLoader_klass()))) {
|
||||||
ik = new (loader_data, size, THREAD) InstanceClassLoaderKlass(
|
ik = new (loader_data, size, THREAD) InstanceClassLoaderKlass(
|
||||||
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
|
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
|
||||||
access_flags, !host_klass.is_null());
|
access_flags, is_anonymous);
|
||||||
} else {
|
} else {
|
||||||
// normal class
|
// normal class
|
||||||
ik = new (loader_data, size, THREAD) InstanceKlass(
|
ik = new (loader_data, size, THREAD) InstanceKlass(
|
||||||
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
|
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
|
||||||
access_flags, !host_klass.is_null());
|
access_flags, is_anonymous);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// reference klass
|
// reference klass
|
||||||
ik = new (loader_data, size, THREAD) InstanceRefKlass(
|
ik = new (loader_data, size, THREAD) InstanceRefKlass(
|
||||||
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
|
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
|
||||||
access_flags, !host_klass.is_null());
|
access_flags, is_anonymous);
|
||||||
}
|
}
|
||||||
|
|
||||||
Atomic::inc(&_total_instanceKlass_count);
|
Atomic::inc(&_total_instanceKlass_count);
|
||||||
@ -2793,7 +2792,10 @@ void InstanceKlass::print_on(outputStream* st) const {
|
|||||||
st->print("%s", source_debug_extension());
|
st->print("%s", source_debug_extension());
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
st->print(BULLET"annotations: "); annotations()->print_value_on(st); st->cr();
|
st->print(BULLET"class annotations: "); class_annotations()->print_value_on(st); st->cr();
|
||||||
|
st->print(BULLET"class type annotations: "); class_type_annotations()->print_value_on(st); st->cr();
|
||||||
|
st->print(BULLET"field annotations: "); fields_annotations()->print_value_on(st); st->cr();
|
||||||
|
st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr();
|
||||||
{
|
{
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
// PreviousVersionInfo objects returned via PreviousVersionWalker
|
// PreviousVersionInfo objects returned via PreviousVersionWalker
|
||||||
|
@ -155,8 +155,8 @@ class InstanceKlass: public Klass {
|
|||||||
ReferenceType rt,
|
ReferenceType rt,
|
||||||
AccessFlags access_flags,
|
AccessFlags access_flags,
|
||||||
Symbol* name,
|
Symbol* name,
|
||||||
Klass* super_klass,
|
Klass* super_klass,
|
||||||
KlassHandle host_klass,
|
bool is_anonymous,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
|
|
||||||
InstanceKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
|
InstanceKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
|
||||||
@ -679,19 +679,19 @@ class InstanceKlass: public Klass {
|
|||||||
// annotations support
|
// annotations support
|
||||||
Annotations* annotations() const { return _annotations; }
|
Annotations* annotations() const { return _annotations; }
|
||||||
void set_annotations(Annotations* anno) { _annotations = anno; }
|
void set_annotations(Annotations* anno) { _annotations = anno; }
|
||||||
|
|
||||||
AnnotationArray* class_annotations() const {
|
AnnotationArray* class_annotations() const {
|
||||||
if (annotations() == NULL) return NULL;
|
return (_annotations != NULL) ? _annotations->class_annotations() : NULL;
|
||||||
return annotations()->class_annotations();
|
|
||||||
}
|
}
|
||||||
Array<AnnotationArray*>* fields_annotations() const {
|
Array<AnnotationArray*>* fields_annotations() const {
|
||||||
if (annotations() == NULL) return NULL;
|
return (_annotations != NULL) ? _annotations->fields_annotations() : NULL;
|
||||||
return annotations()->fields_annotations();
|
|
||||||
}
|
}
|
||||||
Annotations* type_annotations() const {
|
AnnotationArray* class_type_annotations() const {
|
||||||
if (annotations() == NULL) return NULL;
|
return (_annotations != NULL) ? _annotations->class_type_annotations() : NULL;
|
||||||
return annotations()->type_annotations();
|
}
|
||||||
|
Array<AnnotationArray*>* fields_type_annotations() const {
|
||||||
|
return (_annotations != NULL) ? _annotations->fields_type_annotations() : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocation
|
// allocation
|
||||||
instanceOop allocate_instance(TRAPS);
|
instanceOop allocate_instance(TRAPS);
|
||||||
|
|
||||||
@ -810,6 +810,7 @@ class InstanceKlass: public Klass {
|
|||||||
|
|
||||||
// Sizing (in words)
|
// Sizing (in words)
|
||||||
static int header_size() { return align_object_offset(sizeof(InstanceKlass)/HeapWordSize); }
|
static int header_size() { return align_object_offset(sizeof(InstanceKlass)/HeapWordSize); }
|
||||||
|
|
||||||
static int size(int vtable_length, int itable_length,
|
static int size(int vtable_length, int itable_length,
|
||||||
int nonstatic_oop_map_size,
|
int nonstatic_oop_map_size,
|
||||||
bool is_interface, bool is_anonymous) {
|
bool is_interface, bool is_anonymous) {
|
||||||
@ -847,10 +848,14 @@ class InstanceKlass: public Klass {
|
|||||||
return (OopMapBlock*)(start_of_itable() + align_object_offset(itable_length()));
|
return (OopMapBlock*)(start_of_itable() + align_object_offset(itable_length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Klass** end_of_nonstatic_oop_maps() const {
|
||||||
|
return (Klass**)(start_of_nonstatic_oop_maps() +
|
||||||
|
nonstatic_oop_map_count());
|
||||||
|
}
|
||||||
|
|
||||||
Klass** adr_implementor() const {
|
Klass** adr_implementor() const {
|
||||||
if (is_interface()) {
|
if (is_interface()) {
|
||||||
return (Klass**)(start_of_nonstatic_oop_maps() +
|
return (Klass**)end_of_nonstatic_oop_maps();
|
||||||
nonstatic_oop_map_count());
|
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -862,8 +867,7 @@ class InstanceKlass: public Klass {
|
|||||||
if (adr_impl != NULL) {
|
if (adr_impl != NULL) {
|
||||||
return adr_impl + 1;
|
return adr_impl + 1;
|
||||||
} else {
|
} else {
|
||||||
return (Klass**)(start_of_nonstatic_oop_maps() +
|
return end_of_nonstatic_oop_maps();
|
||||||
nonstatic_oop_map_count());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -61,24 +61,14 @@
|
|||||||
Method* Method::allocate(ClassLoaderData* loader_data,
|
Method* Method::allocate(ClassLoaderData* loader_data,
|
||||||
int byte_code_size,
|
int byte_code_size,
|
||||||
AccessFlags access_flags,
|
AccessFlags access_flags,
|
||||||
int compressed_line_number_size,
|
InlineTableSizes* sizes,
|
||||||
int localvariable_table_length,
|
|
||||||
int exception_table_length,
|
|
||||||
int checked_exceptions_length,
|
|
||||||
int method_parameters_length,
|
|
||||||
u2 generic_signature_index,
|
|
||||||
ConstMethod::MethodType method_type,
|
ConstMethod::MethodType method_type,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
assert(!access_flags.is_native() || byte_code_size == 0,
|
assert(!access_flags.is_native() || byte_code_size == 0,
|
||||||
"native methods should not contain byte codes");
|
"native methods should not contain byte codes");
|
||||||
ConstMethod* cm = ConstMethod::allocate(loader_data,
|
ConstMethod* cm = ConstMethod::allocate(loader_data,
|
||||||
byte_code_size,
|
byte_code_size,
|
||||||
compressed_line_number_size,
|
sizes,
|
||||||
localvariable_table_length,
|
|
||||||
exception_table_length,
|
|
||||||
checked_exceptions_length,
|
|
||||||
method_parameters_length,
|
|
||||||
generic_signature_index,
|
|
||||||
method_type,
|
method_type,
|
||||||
CHECK_NULL);
|
CHECK_NULL);
|
||||||
|
|
||||||
@ -317,14 +307,6 @@ Symbol* Method::klass_name() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Method::set_interpreter_kind() {
|
|
||||||
int kind = Interpreter::method_kind(this);
|
|
||||||
assert(kind != Interpreter::invalid,
|
|
||||||
"interpreter entry must be valid");
|
|
||||||
set_interpreter_kind(kind);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Attempt to return method oop to original state. Clear any pointers
|
// Attempt to return method oop to original state. Clear any pointers
|
||||||
// (to objects outside the shared spaces). We won't be able to predict
|
// (to objects outside the shared spaces). We won't be able to predict
|
||||||
// where they should point in a new JVM. Further initialize some
|
// where they should point in a new JVM. Further initialize some
|
||||||
@ -332,7 +314,6 @@ void Method::set_interpreter_kind() {
|
|||||||
|
|
||||||
void Method::remove_unshareable_info() {
|
void Method::remove_unshareable_info() {
|
||||||
unlink_method();
|
unlink_method();
|
||||||
set_interpreter_kind();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1045,9 +1026,9 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid,
|
|||||||
|
|
||||||
methodHandle m;
|
methodHandle m;
|
||||||
{
|
{
|
||||||
|
InlineTableSizes sizes;
|
||||||
Method* m_oop = Method::allocate(loader_data, 0,
|
Method* m_oop = Method::allocate(loader_data, 0,
|
||||||
accessFlags_from(flags_bits),
|
accessFlags_from(flags_bits), &sizes,
|
||||||
0, 0, 0, 0, 0, 0,
|
|
||||||
ConstMethod::NORMAL, CHECK_(empty));
|
ConstMethod::NORMAL, CHECK_(empty));
|
||||||
m = methodHandle(THREAD, m_oop);
|
m = methodHandle(THREAD, m_oop);
|
||||||
}
|
}
|
||||||
@ -1096,22 +1077,35 @@ methodHandle Method::clone_with_new_data(methodHandle m, u_char* new_code, int n
|
|||||||
assert(!m->is_native(), "cannot rewrite native methods");
|
assert(!m->is_native(), "cannot rewrite native methods");
|
||||||
// Allocate new Method*
|
// Allocate new Method*
|
||||||
AccessFlags flags = m->access_flags();
|
AccessFlags flags = m->access_flags();
|
||||||
u2 generic_signature_index = m->generic_signature_index();
|
|
||||||
int checked_exceptions_len = m->checked_exceptions_length();
|
ConstMethod* cm = m->constMethod();
|
||||||
int localvariable_len = m->localvariable_table_length();
|
int checked_exceptions_len = cm->checked_exceptions_length();
|
||||||
int exception_table_len = m->exception_table_length();
|
int localvariable_len = cm->localvariable_table_length();
|
||||||
int method_parameters_len = m->method_parameters_length();
|
int exception_table_len = cm->exception_table_length();
|
||||||
|
int method_parameters_len = cm->method_parameters_length();
|
||||||
|
int method_annotations_len = cm->method_annotations_length();
|
||||||
|
int parameter_annotations_len = cm->parameter_annotations_length();
|
||||||
|
int type_annotations_len = cm->type_annotations_length();
|
||||||
|
int default_annotations_len = cm->default_annotations_length();
|
||||||
|
|
||||||
|
InlineTableSizes sizes(
|
||||||
|
localvariable_len,
|
||||||
|
new_compressed_linenumber_size,
|
||||||
|
exception_table_len,
|
||||||
|
checked_exceptions_len,
|
||||||
|
method_parameters_len,
|
||||||
|
cm->generic_signature_index(),
|
||||||
|
method_annotations_len,
|
||||||
|
parameter_annotations_len,
|
||||||
|
type_annotations_len,
|
||||||
|
default_annotations_len,
|
||||||
|
0);
|
||||||
|
|
||||||
ClassLoaderData* loader_data = m->method_holder()->class_loader_data();
|
ClassLoaderData* loader_data = m->method_holder()->class_loader_data();
|
||||||
Method* newm_oop = Method::allocate(loader_data,
|
Method* newm_oop = Method::allocate(loader_data,
|
||||||
new_code_length,
|
new_code_length,
|
||||||
flags,
|
flags,
|
||||||
new_compressed_linenumber_size,
|
&sizes,
|
||||||
localvariable_len,
|
|
||||||
exception_table_len,
|
|
||||||
checked_exceptions_len,
|
|
||||||
method_parameters_len,
|
|
||||||
generic_signature_index,
|
|
||||||
m->method_type(),
|
m->method_type(),
|
||||||
CHECK_(methodHandle()));
|
CHECK_(methodHandle()));
|
||||||
methodHandle newm (THREAD, newm_oop);
|
methodHandle newm (THREAD, newm_oop);
|
||||||
@ -1311,29 +1305,6 @@ void Method::print_short_name(outputStream* st) {
|
|||||||
MethodHandles::print_as_basic_type_signature_on(st, signature(), true);
|
MethodHandles::print_as_basic_type_signature_on(st, signature(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
|
|
||||||
static void reorder_based_on_method_index(Array<Method*>* methods,
|
|
||||||
Array<AnnotationArray*>* annotations,
|
|
||||||
GrowableArray<AnnotationArray*>* temp_array) {
|
|
||||||
if (annotations == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int length = methods->length();
|
|
||||||
int i;
|
|
||||||
// Copy to temp array
|
|
||||||
temp_array->clear();
|
|
||||||
for (i = 0; i < length; i++) {
|
|
||||||
temp_array->append(annotations->at(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy back using old method indices
|
|
||||||
for (i = 0; i < length; i++) {
|
|
||||||
Method* m = methods->at(i);
|
|
||||||
annotations->at_put(i, temp_array->at(m->method_idnum()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comparer for sorting an object array containing
|
// Comparer for sorting an object array containing
|
||||||
// Method*s.
|
// Method*s.
|
||||||
static int method_comparator(Method* a, Method* b) {
|
static int method_comparator(Method* a, Method* b) {
|
||||||
@ -1341,48 +1312,13 @@ static int method_comparator(Method* a, Method* b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
|
// This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
|
||||||
void Method::sort_methods(Array<Method*>* methods,
|
void Method::sort_methods(Array<Method*>* methods, bool idempotent) {
|
||||||
Array<AnnotationArray*>* methods_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_parameter_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_default_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_type_annotations,
|
|
||||||
bool idempotent) {
|
|
||||||
int length = methods->length();
|
int length = methods->length();
|
||||||
if (length > 1) {
|
if (length > 1) {
|
||||||
bool do_annotations = false;
|
|
||||||
if (methods_annotations != NULL ||
|
|
||||||
methods_parameter_annotations != NULL ||
|
|
||||||
methods_default_annotations != NULL ||
|
|
||||||
methods_type_annotations != NULL) {
|
|
||||||
do_annotations = true;
|
|
||||||
}
|
|
||||||
if (do_annotations) {
|
|
||||||
// Remember current method ordering so we can reorder annotations
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
Method* m = methods->at(i);
|
|
||||||
m->set_method_idnum(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
No_Safepoint_Verifier nsv;
|
No_Safepoint_Verifier nsv;
|
||||||
QuickSort::sort<Method*>(methods->data(), length, method_comparator, idempotent);
|
QuickSort::sort<Method*>(methods->data(), length, method_comparator, idempotent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort annotations if necessary
|
|
||||||
assert(methods_annotations == NULL || methods_annotations->length() == methods->length(), "");
|
|
||||||
assert(methods_parameter_annotations == NULL || methods_parameter_annotations->length() == methods->length(), "");
|
|
||||||
assert(methods_default_annotations == NULL || methods_default_annotations->length() == methods->length(), "");
|
|
||||||
assert(methods_type_annotations == NULL || methods_type_annotations->length() == methods->length(), "");
|
|
||||||
if (do_annotations) {
|
|
||||||
ResourceMark rm;
|
|
||||||
// Allocate temporary storage
|
|
||||||
GrowableArray<AnnotationArray*>* temp_array = new GrowableArray<AnnotationArray*>(length);
|
|
||||||
reorder_based_on_method_index(methods, methods_annotations, temp_array);
|
|
||||||
reorder_based_on_method_index(methods, methods_parameter_annotations, temp_array);
|
|
||||||
reorder_based_on_method_index(methods, methods_default_annotations, temp_array);
|
|
||||||
reorder_based_on_method_index(methods, methods_type_annotations, temp_array);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset method ordering
|
// Reset method ordering
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
Method* m = methods->at(i);
|
Method* m = methods->at(i);
|
||||||
|
@ -101,6 +101,7 @@ class LocalVariableTableElement;
|
|||||||
class AdapterHandlerEntry;
|
class AdapterHandlerEntry;
|
||||||
class MethodData;
|
class MethodData;
|
||||||
class ConstMethod;
|
class ConstMethod;
|
||||||
|
class InlineTableSizes;
|
||||||
class KlassSizeStats;
|
class KlassSizeStats;
|
||||||
|
|
||||||
class Method : public Metadata {
|
class Method : public Metadata {
|
||||||
@ -157,12 +158,7 @@ class Method : public Metadata {
|
|||||||
static Method* allocate(ClassLoaderData* loader_data,
|
static Method* allocate(ClassLoaderData* loader_data,
|
||||||
int byte_code_size,
|
int byte_code_size,
|
||||||
AccessFlags access_flags,
|
AccessFlags access_flags,
|
||||||
int compressed_line_number_size,
|
InlineTableSizes* sizes,
|
||||||
int localvariable_table_length,
|
|
||||||
int exception_table_length,
|
|
||||||
int checked_exceptions_length,
|
|
||||||
int method_parameters_length,
|
|
||||||
u2 generic_signature_index,
|
|
||||||
ConstMethod::MethodType method_type,
|
ConstMethod::MethodType method_type,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
|
|
||||||
@ -207,33 +203,17 @@ class Method : public Metadata {
|
|||||||
|
|
||||||
// annotations support
|
// annotations support
|
||||||
AnnotationArray* annotations() const {
|
AnnotationArray* annotations() const {
|
||||||
InstanceKlass* ik = method_holder();
|
return constMethod()->method_annotations();
|
||||||
if (ik->annotations() == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return ik->annotations()->get_method_annotations_of(method_idnum());
|
|
||||||
}
|
}
|
||||||
AnnotationArray* parameter_annotations() const {
|
AnnotationArray* parameter_annotations() const {
|
||||||
InstanceKlass* ik = method_holder();
|
return constMethod()->parameter_annotations();
|
||||||
if (ik->annotations() == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return ik->annotations()->get_method_parameter_annotations_of(method_idnum());
|
|
||||||
}
|
}
|
||||||
AnnotationArray* annotation_default() const {
|
AnnotationArray* annotation_default() const {
|
||||||
InstanceKlass* ik = method_holder();
|
return constMethod()->default_annotations();
|
||||||
if (ik->annotations() == NULL) {
|
}
|
||||||
return NULL;
|
AnnotationArray* type_annotations() const {
|
||||||
}
|
return constMethod()->type_annotations();
|
||||||
return ik->annotations()->get_method_default_annotations_of(method_idnum());
|
|
||||||
}
|
}
|
||||||
AnnotationArray* type_annotations() const {
|
|
||||||
InstanceKlass* ik = method_holder();
|
|
||||||
Annotations* type_annos = ik->type_annotations();
|
|
||||||
if (type_annos == NULL)
|
|
||||||
return NULL;
|
|
||||||
return type_annos->get_method_annotations_of(method_idnum());
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CC_INTERP
|
#ifdef CC_INTERP
|
||||||
void set_result_index(BasicType type);
|
void set_result_index(BasicType type);
|
||||||
@ -439,13 +419,6 @@ class Method : public Metadata {
|
|||||||
address interpreter_entry() const { return _i2i_entry; }
|
address interpreter_entry() const { return _i2i_entry; }
|
||||||
// Only used when first initialize so we can set _i2i_entry and _from_interpreted_entry
|
// Only used when first initialize so we can set _i2i_entry and _from_interpreted_entry
|
||||||
void set_interpreter_entry(address entry) { _i2i_entry = entry; _from_interpreted_entry = entry; }
|
void set_interpreter_entry(address entry) { _i2i_entry = entry; _from_interpreted_entry = entry; }
|
||||||
int interpreter_kind(void) {
|
|
||||||
return constMethod()->interpreter_kind();
|
|
||||||
}
|
|
||||||
void set_interpreter_kind();
|
|
||||||
void set_interpreter_kind(int kind) {
|
|
||||||
constMethod()->set_interpreter_kind(kind);
|
|
||||||
}
|
|
||||||
|
|
||||||
// native function (used for native methods only)
|
// native function (used for native methods only)
|
||||||
enum {
|
enum {
|
||||||
@ -808,12 +781,7 @@ class Method : public Metadata {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Helper routine used for method sorting
|
// Helper routine used for method sorting
|
||||||
static void sort_methods(Array<Method*>* methods,
|
static void sort_methods(Array<Method*>* methods, bool idempotent = false);
|
||||||
Array<AnnotationArray*>* methods_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_parameter_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_default_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_type_annotations,
|
|
||||||
bool idempotent = false);
|
|
||||||
|
|
||||||
// Deallocation function for redefine classes or if an error occurs
|
// Deallocation function for redefine classes or if an error occurs
|
||||||
void deallocate_contents(ClassLoaderData* loader_data);
|
void deallocate_contents(ClassLoaderData* loader_data);
|
||||||
|
@ -1573,9 +1573,9 @@ JVM_ENTRY(jbyteArray, JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls))
|
|||||||
if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) {
|
if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) {
|
||||||
Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls));
|
Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls));
|
||||||
if (k->oop_is_instance()) {
|
if (k->oop_is_instance()) {
|
||||||
Annotations* type_annotations = InstanceKlass::cast(k)->type_annotations();
|
AnnotationArray* type_annotations = InstanceKlass::cast(k)->class_type_annotations();
|
||||||
if (type_annotations != NULL) {
|
if (type_annotations != NULL) {
|
||||||
typeArrayOop a = Annotations::make_java_array(type_annotations->class_annotations(), CHECK_NULL);
|
typeArrayOop a = Annotations::make_java_array(type_annotations, CHECK_NULL);
|
||||||
return (jbyteArray) JNIHandles::make_local(env, a);
|
return (jbyteArray) JNIHandles::make_local(env, a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -492,26 +492,6 @@ int VM_RedefineClasses::find_or_append_indirect_entry(constantPoolHandle scratch
|
|||||||
} // end find_or_append_indirect_entry()
|
} // end find_or_append_indirect_entry()
|
||||||
|
|
||||||
|
|
||||||
void VM_RedefineClasses::swap_all_method_annotations(int i, int j, instanceKlassHandle scratch_class, TRAPS) {
|
|
||||||
AnnotationArray* save;
|
|
||||||
|
|
||||||
Annotations* sca = scratch_class->annotations();
|
|
||||||
if (sca == NULL) return;
|
|
||||||
|
|
||||||
save = sca->get_method_annotations_of(i);
|
|
||||||
sca->set_method_annotations_of(scratch_class, i, sca->get_method_annotations_of(j), CHECK);
|
|
||||||
sca->set_method_annotations_of(scratch_class, j, save, CHECK);
|
|
||||||
|
|
||||||
save = sca->get_method_parameter_annotations_of(i);
|
|
||||||
sca->set_method_parameter_annotations_of(scratch_class, i, sca->get_method_parameter_annotations_of(j), CHECK);
|
|
||||||
sca->set_method_parameter_annotations_of(scratch_class, j, save, CHECK);
|
|
||||||
|
|
||||||
save = sca->get_method_default_annotations_of(i);
|
|
||||||
sca->set_method_default_annotations_of(scratch_class, i, sca->get_method_default_annotations_of(j), CHECK);
|
|
||||||
sca->set_method_default_annotations_of(scratch_class, j, save, CHECK);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
|
jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
|
||||||
instanceKlassHandle the_class,
|
instanceKlassHandle the_class,
|
||||||
instanceKlassHandle scratch_class) {
|
instanceKlassHandle scratch_class) {
|
||||||
@ -693,10 +673,9 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
|
|||||||
idnum_owner->set_method_idnum(new_num);
|
idnum_owner->set_method_idnum(new_num);
|
||||||
}
|
}
|
||||||
k_new_method->set_method_idnum(old_num);
|
k_new_method->set_method_idnum(old_num);
|
||||||
swap_all_method_annotations(old_num, new_num, scratch_class, thread);
|
if (thread->has_pending_exception()) {
|
||||||
if (thread->has_pending_exception()) {
|
return JVMTI_ERROR_OUT_OF_MEMORY;
|
||||||
return JVMTI_ERROR_OUT_OF_MEMORY;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RC_TRACE(0x00008000, ("Method matched: new: %s [%d] == old: %s [%d]",
|
RC_TRACE(0x00008000, ("Method matched: new: %s [%d] == old: %s [%d]",
|
||||||
@ -729,7 +708,6 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
|
|||||||
idnum_owner->set_method_idnum(new_num);
|
idnum_owner->set_method_idnum(new_num);
|
||||||
}
|
}
|
||||||
k_new_method->set_method_idnum(num);
|
k_new_method->set_method_idnum(num);
|
||||||
swap_all_method_annotations(new_num, num, scratch_class, thread);
|
|
||||||
if (thread->has_pending_exception()) {
|
if (thread->has_pending_exception()) {
|
||||||
return JVMTI_ERROR_OUT_OF_MEMORY;
|
return JVMTI_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
@ -1895,10 +1873,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_element_value(
|
|||||||
bool VM_RedefineClasses::rewrite_cp_refs_in_fields_annotations(
|
bool VM_RedefineClasses::rewrite_cp_refs_in_fields_annotations(
|
||||||
instanceKlassHandle scratch_class, TRAPS) {
|
instanceKlassHandle scratch_class, TRAPS) {
|
||||||
|
|
||||||
Annotations* sca = scratch_class->annotations();
|
Array<AnnotationArray*>* fields_annotations = scratch_class->fields_annotations();
|
||||||
if (sca == NULL) return true;
|
|
||||||
|
|
||||||
Array<AnnotationArray*>* fields_annotations = sca->fields_annotations();
|
|
||||||
|
|
||||||
if (fields_annotations == NULL || fields_annotations->length() == 0) {
|
if (fields_annotations == NULL || fields_annotations->length() == 0) {
|
||||||
// no fields_annotations so nothing to do
|
// no fields_annotations so nothing to do
|
||||||
@ -1933,21 +1908,10 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_fields_annotations(
|
|||||||
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_annotations(
|
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_annotations(
|
||||||
instanceKlassHandle scratch_class, TRAPS) {
|
instanceKlassHandle scratch_class, TRAPS) {
|
||||||
|
|
||||||
Annotations* sca = scratch_class->annotations();
|
for (int i = 0; i < scratch_class->methods()->length(); i++) {
|
||||||
if (sca == NULL) return true;
|
Method* m = scratch_class->methods()->at(i);
|
||||||
|
AnnotationArray* method_annotations = m->constMethod()->method_annotations();
|
||||||
|
|
||||||
Array<AnnotationArray*>* methods_annotations = sca->methods_annotations();
|
|
||||||
|
|
||||||
if (methods_annotations == NULL || methods_annotations->length() == 0) {
|
|
||||||
// no methods_annotations so nothing to do
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
RC_TRACE_WITH_THREAD(0x02000000, THREAD,
|
|
||||||
("methods_annotations length=%d", methods_annotations->length()));
|
|
||||||
|
|
||||||
for (int i = 0; i < methods_annotations->length(); i++) {
|
|
||||||
AnnotationArray* method_annotations = methods_annotations->at(i);
|
|
||||||
if (method_annotations == NULL || method_annotations->length() == 0) {
|
if (method_annotations == NULL || method_annotations->length() == 0) {
|
||||||
// this method does not have any annotations so skip it
|
// this method does not have any annotations so skip it
|
||||||
continue;
|
continue;
|
||||||
@ -1983,24 +1947,9 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_methods_annotations(
|
|||||||
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_parameter_annotations(
|
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_parameter_annotations(
|
||||||
instanceKlassHandle scratch_class, TRAPS) {
|
instanceKlassHandle scratch_class, TRAPS) {
|
||||||
|
|
||||||
Annotations* sca = scratch_class->annotations();
|
for (int i = 0; i < scratch_class->methods()->length(); i++) {
|
||||||
if (sca == NULL) return true;
|
Method* m = scratch_class->methods()->at(i);
|
||||||
|
AnnotationArray* method_parameter_annotations = m->constMethod()->parameter_annotations();
|
||||||
Array<AnnotationArray*>* methods_parameter_annotations =
|
|
||||||
sca->methods_parameter_annotations();
|
|
||||||
|
|
||||||
if (methods_parameter_annotations == NULL
|
|
||||||
|| methods_parameter_annotations->length() == 0) {
|
|
||||||
// no methods_parameter_annotations so nothing to do
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
RC_TRACE_WITH_THREAD(0x02000000, THREAD,
|
|
||||||
("methods_parameter_annotations length=%d",
|
|
||||||
methods_parameter_annotations->length()));
|
|
||||||
|
|
||||||
for (int i = 0; i < methods_parameter_annotations->length(); i++) {
|
|
||||||
AnnotationArray* method_parameter_annotations = methods_parameter_annotations->at(i);
|
|
||||||
if (method_parameter_annotations == NULL
|
if (method_parameter_annotations == NULL
|
||||||
|| method_parameter_annotations->length() == 0) {
|
|| method_parameter_annotations->length() == 0) {
|
||||||
// this method does not have any parameter annotations so skip it
|
// this method does not have any parameter annotations so skip it
|
||||||
@ -2050,24 +1999,9 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_methods_parameter_annotations(
|
|||||||
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_default_annotations(
|
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_default_annotations(
|
||||||
instanceKlassHandle scratch_class, TRAPS) {
|
instanceKlassHandle scratch_class, TRAPS) {
|
||||||
|
|
||||||
Annotations* sca = scratch_class->annotations();
|
for (int i = 0; i < scratch_class->methods()->length(); i++) {
|
||||||
if (sca == NULL) return true;
|
Method* m = scratch_class->methods()->at(i);
|
||||||
|
AnnotationArray* method_default_annotations = m->constMethod()->default_annotations();
|
||||||
Array<AnnotationArray*>* methods_default_annotations =
|
|
||||||
sca->methods_default_annotations();
|
|
||||||
|
|
||||||
if (methods_default_annotations == NULL
|
|
||||||
|| methods_default_annotations->length() == 0) {
|
|
||||||
// no methods_default_annotations so nothing to do
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
RC_TRACE_WITH_THREAD(0x02000000, THREAD,
|
|
||||||
("methods_default_annotations length=%d",
|
|
||||||
methods_default_annotations->length()));
|
|
||||||
|
|
||||||
for (int i = 0; i < methods_default_annotations->length(); i++) {
|
|
||||||
AnnotationArray* method_default_annotations = methods_default_annotations->at(i);
|
|
||||||
if (method_default_annotations == NULL
|
if (method_default_annotations == NULL
|
||||||
|| method_default_annotations->length() == 0) {
|
|| method_default_annotations->length() == 0) {
|
||||||
// this method does not have any default annotations so skip it
|
// this method does not have any default annotations so skip it
|
||||||
@ -3072,6 +3006,31 @@ void VM_RedefineClasses::compute_added_deleted_matching_methods() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VM_RedefineClasses::swap_annotations(instanceKlassHandle the_class,
|
||||||
|
instanceKlassHandle scratch_class) {
|
||||||
|
// Since there is currently no rewriting of type annotations indexes
|
||||||
|
// into the CP, we null out type annotations on scratch_class before
|
||||||
|
// we swap annotations with the_class rather than facing the
|
||||||
|
// possibility of shipping annotations with broken indexes to
|
||||||
|
// Java-land.
|
||||||
|
ClassLoaderData* loader_data = scratch_class->class_loader_data();
|
||||||
|
AnnotationArray* new_class_type_annotations = scratch_class->class_type_annotations();
|
||||||
|
if (new_class_type_annotations != NULL) {
|
||||||
|
MetadataFactory::free_array<u1>(loader_data, new_class_type_annotations);
|
||||||
|
scratch_class->annotations()->set_class_type_annotations(NULL);
|
||||||
|
}
|
||||||
|
Array<AnnotationArray*>* new_field_type_annotations = scratch_class->fields_type_annotations();
|
||||||
|
if (new_field_type_annotations != NULL) {
|
||||||
|
Annotations::free_contents(loader_data, new_field_type_annotations);
|
||||||
|
scratch_class->annotations()->set_fields_type_annotations(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap annotation fields values
|
||||||
|
Annotations* old_annotations = the_class->annotations();
|
||||||
|
the_class->set_annotations(scratch_class->annotations());
|
||||||
|
scratch_class->set_annotations(old_annotations);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Install the redefinition of a class:
|
// Install the redefinition of a class:
|
||||||
// - house keeping (flushing breakpoints and caches, deoptimizing
|
// - house keeping (flushing breakpoints and caches, deoptimizing
|
||||||
@ -3282,23 +3241,7 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
|
|||||||
the_class->set_access_flags(flags);
|
the_class->set_access_flags(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since there is currently no rewriting of type annotations indexes
|
swap_annotations(the_class, scratch_class);
|
||||||
// into the CP, we null out type annotations on scratch_class before
|
|
||||||
// we swap annotations with the_class rather than facing the
|
|
||||||
// possibility of shipping annotations with broken indexes to
|
|
||||||
// Java-land.
|
|
||||||
Annotations* new_annotations = scratch_class->annotations();
|
|
||||||
if (new_annotations != NULL) {
|
|
||||||
Annotations* new_type_annotations = new_annotations->type_annotations();
|
|
||||||
if (new_type_annotations != NULL) {
|
|
||||||
MetadataFactory::free_metadata(scratch_class->class_loader_data(), new_type_annotations);
|
|
||||||
new_annotations->set_type_annotations(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Swap annotation fields values
|
|
||||||
Annotations* old_annotations = the_class->annotations();
|
|
||||||
the_class->set_annotations(scratch_class->annotations());
|
|
||||||
scratch_class->set_annotations(old_annotations);
|
|
||||||
|
|
||||||
// Replace minor version number of class file
|
// Replace minor version number of class file
|
||||||
u2 old_minor_version = the_class->minor_version();
|
u2 old_minor_version = the_class->minor_version();
|
||||||
|
@ -384,11 +384,6 @@ class VM_RedefineClasses: public VM_Operation {
|
|||||||
jvmtiError compare_and_normalize_class_versions(
|
jvmtiError compare_and_normalize_class_versions(
|
||||||
instanceKlassHandle the_class, instanceKlassHandle scratch_class);
|
instanceKlassHandle the_class, instanceKlassHandle scratch_class);
|
||||||
|
|
||||||
// Swap annotations[i] with annotations[j]
|
|
||||||
// Used by compare_and_normalize_class_versions() when normalizing
|
|
||||||
// overloaded methods or changing idnum as when adding or deleting methods.
|
|
||||||
void swap_all_method_annotations(int i, int j, instanceKlassHandle scratch_class, TRAPS);
|
|
||||||
|
|
||||||
// Figure out which new methods match old methods in name and signature,
|
// Figure out which new methods match old methods in name and signature,
|
||||||
// which methods have been added, and which are no longer present
|
// which methods have been added, and which are no longer present
|
||||||
void compute_added_deleted_matching_methods();
|
void compute_added_deleted_matching_methods();
|
||||||
@ -417,6 +412,9 @@ class VM_RedefineClasses: public VM_Operation {
|
|||||||
void redefine_single_class(jclass the_jclass,
|
void redefine_single_class(jclass the_jclass,
|
||||||
Klass* scratch_class_oop, TRAPS);
|
Klass* scratch_class_oop, TRAPS);
|
||||||
|
|
||||||
|
void swap_annotations(instanceKlassHandle new_class,
|
||||||
|
instanceKlassHandle scratch_class);
|
||||||
|
|
||||||
// Increment the classRedefinedCount field in the specific InstanceKlass
|
// Increment the classRedefinedCount field in the specific InstanceKlass
|
||||||
// and in all direct and indirect subclasses.
|
// and in all direct and indirect subclasses.
|
||||||
void increment_class_counter(InstanceKlass *ik, TRAPS);
|
void increment_class_counter(InstanceKlass *ik, TRAPS);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -67,13 +67,10 @@ AnnotationArray* fieldDescriptor::annotations() const {
|
|||||||
|
|
||||||
AnnotationArray* fieldDescriptor::type_annotations() const {
|
AnnotationArray* fieldDescriptor::type_annotations() const {
|
||||||
InstanceKlass* ik = field_holder();
|
InstanceKlass* ik = field_holder();
|
||||||
Annotations* type_annos = ik->type_annotations();
|
Array<AnnotationArray*>* type_annos = ik->fields_type_annotations();
|
||||||
if (type_annos == NULL)
|
if (type_annos == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
Array<AnnotationArray*>* md = type_annos->fields_annotations();
|
return type_annos->at(index());
|
||||||
if (md == NULL)
|
|
||||||
return NULL;
|
|
||||||
return md->at(index());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constantTag fieldDescriptor::initial_value_tag() const {
|
constantTag fieldDescriptor::initial_value_tag() const {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -366,11 +366,10 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
|
|||||||
volatile_nonstatic_field(Method, _from_compiled_entry, address) \
|
volatile_nonstatic_field(Method, _from_compiled_entry, address) \
|
||||||
volatile_nonstatic_field(Method, _from_interpreted_entry, address) \
|
volatile_nonstatic_field(Method, _from_interpreted_entry, address) \
|
||||||
volatile_nonstatic_field(ConstMethod, _fingerprint, uint64_t) \
|
volatile_nonstatic_field(ConstMethod, _fingerprint, uint64_t) \
|
||||||
nonstatic_field(ConstMethod, _constants, ConstantPool*) \
|
nonstatic_field(ConstMethod, _constants, ConstantPool*) \
|
||||||
nonstatic_field(ConstMethod, _stackmap_data, Array<u1>*) \
|
nonstatic_field(ConstMethod, _stackmap_data, Array<u1>*) \
|
||||||
nonstatic_field(ConstMethod, _constMethod_size, int) \
|
nonstatic_field(ConstMethod, _constMethod_size, int) \
|
||||||
nonstatic_field(ConstMethod, _interpreter_kind, jbyte) \
|
nonstatic_field(ConstMethod, _flags, u2) \
|
||||||
nonstatic_field(ConstMethod, _flags, jbyte) \
|
|
||||||
nonstatic_field(ConstMethod, _code_size, u2) \
|
nonstatic_field(ConstMethod, _code_size, u2) \
|
||||||
nonstatic_field(ConstMethod, _name_index, u2) \
|
nonstatic_field(ConstMethod, _name_index, u2) \
|
||||||
nonstatic_field(ConstMethod, _signature_index, u2) \
|
nonstatic_field(ConstMethod, _signature_index, u2) \
|
||||||
@ -2261,14 +2260,18 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
|
|||||||
declare_constant(Klass::_lh_array_tag_obj_value) \
|
declare_constant(Klass::_lh_array_tag_obj_value) \
|
||||||
\
|
\
|
||||||
/********************************/ \
|
/********************************/ \
|
||||||
/* ConstMethod anon-enum */ \
|
/* ConstMethod anon-enum */ \
|
||||||
/********************************/ \
|
/********************************/ \
|
||||||
\
|
\
|
||||||
declare_constant(ConstMethod::_has_linenumber_table) \
|
declare_constant(ConstMethod::_has_linenumber_table) \
|
||||||
declare_constant(ConstMethod::_has_checked_exceptions) \
|
declare_constant(ConstMethod::_has_checked_exceptions) \
|
||||||
declare_constant(ConstMethod::_has_localvariable_table) \
|
declare_constant(ConstMethod::_has_localvariable_table) \
|
||||||
declare_constant(ConstMethod::_has_exception_table) \
|
declare_constant(ConstMethod::_has_exception_table) \
|
||||||
declare_constant(ConstMethod::_has_generic_signature) \
|
declare_constant(ConstMethod::_has_generic_signature) \
|
||||||
|
declare_constant(ConstMethod::_has_method_annotations) \
|
||||||
|
declare_constant(ConstMethod::_has_parameter_annotations) \
|
||||||
|
declare_constant(ConstMethod::_has_default_annotations) \
|
||||||
|
declare_constant(ConstMethod::_has_type_annotations) \
|
||||||
\
|
\
|
||||||
/*************************************/ \
|
/*************************************/ \
|
||||||
/* InstanceKlass enum */ \
|
/* InstanceKlass enum */ \
|
||||||
|
148
hotspot/test/runtime/8007320/ConstMethodTest.java
Normal file
148
hotspot/test/runtime/8007320/ConstMethodTest.java
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8007320
|
||||||
|
* @summary Test all optional fields in ConstMethod
|
||||||
|
* @compile -g -parameters ConstMethodTest.java
|
||||||
|
* @run main ConstMethodTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@interface MyAnnotation {
|
||||||
|
public String name();
|
||||||
|
public String value();
|
||||||
|
public String date() default "today";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.TYPE_USE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@interface TypeAnno {
|
||||||
|
String value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.TYPE_USE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@interface TypeAnno2 {
|
||||||
|
String value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.PARAMETER)
|
||||||
|
@interface Named {
|
||||||
|
String value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@interface ScalarTypesWithDefault {
|
||||||
|
byte b() default 11;
|
||||||
|
short s() default 12;
|
||||||
|
int i() default 13;
|
||||||
|
long l() default 14;
|
||||||
|
char c() default 'V';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some exception class
|
||||||
|
class OkException extends RuntimeException {};
|
||||||
|
|
||||||
|
|
||||||
|
@MyAnnotation(name="someName", value = "Hello World")
|
||||||
|
public class ConstMethodTest {
|
||||||
|
|
||||||
|
private static void check(boolean b) {
|
||||||
|
if (!b)
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
private static void fail(String msg) {
|
||||||
|
System.err.println(msg);
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
private static void equal(Object x, Object y) {
|
||||||
|
if (x == null ? y == null : x.equals(y)) {
|
||||||
|
} else {
|
||||||
|
fail(x + " not equal to " + y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static final String[] parameter_names = {
|
||||||
|
"parameter", "parameter2", "x"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Declare a function with everything in it.
|
||||||
|
@MyAnnotation(name="someName", value="Hello World")
|
||||||
|
static <T> void kitchenSinkFunc(@Named(value="aName") String parameter,
|
||||||
|
@Named("bName") String parameter2,
|
||||||
|
@ScalarTypesWithDefault T x)
|
||||||
|
throws @TypeAnno("RE") @TypeAnno2("RE2") RuntimeException,
|
||||||
|
NullPointerException,
|
||||||
|
@TypeAnno("AIOOBE") ArrayIndexOutOfBoundsException {
|
||||||
|
int i, j, k;
|
||||||
|
try {
|
||||||
|
System.out.println("calling kitchenSinkFunc " + parameter);
|
||||||
|
throw new OkException(); // to see stack trace with line numbers
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void test1() throws Throwable {
|
||||||
|
for (Method m : ConstMethodTest.class.getDeclaredMethods()) {
|
||||||
|
if (m.getName().equals("kitchenSinkFunc")) {
|
||||||
|
Annotation[][] ann = m.getParameterAnnotations();
|
||||||
|
equal(ann.length, 3);
|
||||||
|
Annotation foo = ann[0][0];
|
||||||
|
Annotation bar = ann[1][0];
|
||||||
|
equal(foo.toString(), "@Named(value=aName)");
|
||||||
|
equal(bar.toString(), "@Named(value=bName)");
|
||||||
|
check(foo.equals(foo));
|
||||||
|
check(bar.equals(bar));
|
||||||
|
check(! foo.equals(bar));
|
||||||
|
// method annotations
|
||||||
|
Annotation[] ann2 = m.getAnnotations();
|
||||||
|
equal(ann2.length, 1);
|
||||||
|
Annotation mann = ann2[0];
|
||||||
|
equal(mann.toString(), "@MyAnnotation(date=today, name=someName, value=Hello World)");
|
||||||
|
// Test Method parameter names
|
||||||
|
Parameter[] parameters = m.getParameters();
|
||||||
|
if(parameters == null)
|
||||||
|
throw new Exception("getParameters should never be null");
|
||||||
|
for(int i = 0; i < parameters.length; i++) {
|
||||||
|
Parameter p = parameters[i];
|
||||||
|
equal(parameters[i].getName(), parameter_names[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(java.lang.String[] unused) throws Throwable {
|
||||||
|
// pass 5 so kitchenSinkFunc is instantiated with an int
|
||||||
|
kitchenSinkFunc("parameter", "param2", 5);
|
||||||
|
test1();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user