EVALUATION
In /src/share/vm/classfile/classFileParser.cpp, in the
function ClassFileParser::parse_method(), the following
block of code is interesting:
/* 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) {
int tbl_no, idx;
promoted_flags->set_has_localvariable_table();
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 = 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);
}
It looks like the LVT (and LVTT) are copied out when the class file
is parsed and put on the side.
|
EVALUATION
The JVM/TI RetransformClasses() API uses the
JvmtiClassFileReconstituter class to get the bytecode
to pass to the ClassFileLoadHook event.
The src/share/vm/prims/jvmtiClassFileReconstituter.cpp
file has the following interesting comments:
// FIXME: add Deprecated, LVT, LVTT attributes
// FIXME: fix Synthetic attribute
// FIXME: per Serguei, add error return handling for constantPoolOopDesc::copy_cpool_bytes()
<snip>
void JvmtiClassFileReconstituter::write_code_attribute(methodHandle method) {
constMethodHandle const_method(thread(), method->constMethod());
u2 line_num_cnt = 0;
int stackmap_len = 0;
// compute number and length of attributes -- FIXME: for now no LVT
<snip>
if (stackmap_len != 0) {
write_stackmap_table_attribute(method, stackmap_len);
}
// FIXME: write LVT attribute
}
I'm moving this bug from java/java/classes_instrument to
jvm/hotspot/jvmti.
|