Path: blob/master/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp
41144 views
/*1* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "classfile/symbolTable.hpp"26#include "interpreter/bytecodeStream.hpp"27#include "memory/universe.hpp"28#include "oops/fieldStreams.inline.hpp"29#include "oops/recordComponent.hpp"30#include "prims/jvmtiClassFileReconstituter.hpp"31#include "runtime/handles.inline.hpp"32#include "runtime/signature.hpp"33#include "utilities/bytes.hpp"3435// FIXME: add Deprecated attribute36// FIXME: fix Synthetic attribute37// FIXME: per Serguei, add error return handling for ConstantPool::copy_cpool_bytes()3839JvmtiConstantPoolReconstituter::JvmtiConstantPoolReconstituter(InstanceKlass* ik) {40set_error(JVMTI_ERROR_NONE);41_ik = ik;42_cpool = constantPoolHandle(Thread::current(), ik->constants());43_symmap = new SymbolHashMap();44_classmap = new SymbolHashMap();45_cpool_size = _cpool->hash_entries_to(_symmap, _classmap);46if (_cpool_size == 0) {47set_error(JVMTI_ERROR_OUT_OF_MEMORY);48} else if (_cpool_size < 0) {49set_error(JVMTI_ERROR_INTERNAL);50}51}5253// Write the field information portion of ClassFile structure54// JVMSpec| u2 fields_count;55// JVMSpec| field_info fields[fields_count];56void JvmtiClassFileReconstituter::write_field_infos() {57HandleMark hm(thread());58Array<AnnotationArray*>* fields_anno = ik()->fields_annotations();59Array<AnnotationArray*>* fields_type_anno = ik()->fields_type_annotations();6061// Compute the real number of Java fields62int java_fields = ik()->java_fields_count();6364write_u2(java_fields);65for (JavaFieldStream fs(ik()); !fs.done(); fs.next()) {66AccessFlags access_flags = fs.access_flags();67int name_index = fs.name_index();68int signature_index = fs.signature_index();69int initial_value_index = fs.initval_index();70guarantee(name_index != 0 && signature_index != 0, "bad constant pool index for field");71// int offset = ik()->field_offset( index );72int generic_signature_index = fs.generic_signature_index();73AnnotationArray* anno = fields_anno == NULL ? NULL : fields_anno->at(fs.index());74AnnotationArray* type_anno = fields_type_anno == NULL ? NULL : fields_type_anno->at(fs.index());7576// JVMSpec| field_info {77// JVMSpec| u2 access_flags;78// JVMSpec| u2 name_index;79// JVMSpec| u2 descriptor_index;80// JVMSpec| u2 attributes_count;81// JVMSpec| attribute_info attributes[attributes_count];82// JVMSpec| }8384write_u2(access_flags.as_int() & JVM_RECOGNIZED_FIELD_MODIFIERS);85write_u2(name_index);86write_u2(signature_index);87int attr_count = 0;88if (initial_value_index != 0) {89++attr_count;90}91if (access_flags.is_synthetic()) {92// ++attr_count;93}94if (generic_signature_index != 0) {95++attr_count;96}97if (anno != NULL) {98++attr_count; // has RuntimeVisibleAnnotations attribute99}100if (type_anno != NULL) {101++attr_count; // has RuntimeVisibleTypeAnnotations attribute102}103104write_u2(attr_count);105106if (initial_value_index != 0) {107write_attribute_name_index("ConstantValue");108write_u4(2); //length always 2109write_u2(initial_value_index);110}111if (access_flags.is_synthetic()) {112// write_synthetic_attribute();113}114if (generic_signature_index != 0) {115write_signature_attribute(generic_signature_index);116}117if (anno != NULL) {118write_annotations_attribute("RuntimeVisibleAnnotations", anno);119}120if (type_anno != NULL) {121write_annotations_attribute("RuntimeVisibleTypeAnnotations", type_anno);122}123}124}125126// Write Code attribute127// JVMSpec| Code_attribute {128// JVMSpec| u2 attribute_name_index;129// JVMSpec| u4 attribute_length;130// JVMSpec| u2 max_stack;131// JVMSpec| u2 max_locals;132// JVMSpec| u4 code_length;133// JVMSpec| u1 code[code_length];134// JVMSpec| u2 exception_table_length;135// JVMSpec| { u2 start_pc;136// JVMSpec| u2 end_pc;137// JVMSpec| u2 handler_pc;138// JVMSpec| u2 catch_type;139// JVMSpec| } exception_table[exception_table_length];140// JVMSpec| u2 attributes_count;141// JVMSpec| attribute_info attributes[attributes_count];142// JVMSpec| }143void JvmtiClassFileReconstituter::write_code_attribute(const methodHandle& method) {144ConstMethod* const_method = method->constMethod();145u2 line_num_cnt = 0;146int stackmap_len = 0;147int local_variable_table_length = 0;148int local_variable_type_table_length = 0;149150// compute number and length of attributes151int attr_count = 0;152int attr_size = 0;153if (const_method->has_linenumber_table()) {154line_num_cnt = line_number_table_entries(method);155if (line_num_cnt != 0) {156++attr_count;157// Compute the complete size of the line number table attribute:158// LineNumberTable_attribute {159// u2 attribute_name_index;160// u4 attribute_length;161// u2 line_number_table_length;162// { u2 start_pc;163// u2 line_number;164// } line_number_table[line_number_table_length];165// }166attr_size += 2 + 4 + 2 + line_num_cnt * (2 + 2);167}168}169if (method->has_stackmap_table()) {170stackmap_len = method->stackmap_data()->length();171if (stackmap_len != 0) {172++attr_count;173// Compute the size of the stack map table attribute (VM stores raw):174// StackMapTable_attribute {175// u2 attribute_name_index;176// u4 attribute_length;177// u2 number_of_entries;178// stack_map_frame_entries[number_of_entries];179// }180attr_size += 2 + 4 + stackmap_len;181}182}183if (method->has_localvariable_table()) {184local_variable_table_length = method->localvariable_table_length();185if (local_variable_table_length != 0) {186++attr_count;187// Compute the size of the local variable table attribute (VM stores raw):188// LocalVariableTable_attribute {189// u2 attribute_name_index;190// u4 attribute_length;191// u2 local_variable_table_length;192// {193// u2 start_pc;194// u2 length;195// u2 name_index;196// u2 descriptor_index;197// u2 index;198// }199attr_size += 2 + 4 + 2 + local_variable_table_length * (2 + 2 + 2 + 2 + 2);200201// Local variables with generic signatures must have LVTT entries202LocalVariableTableElement *elem = method->localvariable_table_start();203for (int idx = 0; idx < local_variable_table_length; idx++) {204if (elem[idx].signature_cp_index != 0) {205local_variable_type_table_length++;206}207}208209if (local_variable_type_table_length != 0) {210++attr_count;211// Compute the size of the local variable type table attribute (VM stores raw):212// LocalVariableTypeTable_attribute {213// u2 attribute_name_index;214// u4 attribute_length;215// u2 local_variable_type_table_length;216// {217// u2 start_pc;218// u2 length;219// u2 name_index;220// u2 signature_index;221// u2 index;222// }223attr_size += 2 + 4 + 2 + local_variable_type_table_length * (2 + 2 + 2 + 2 + 2);224}225}226}227228ExceptionTable exception_table(method());229int exception_table_length = exception_table.length();230int code_size = const_method->code_size();231int size =2322+2+4 + // max_stack, max_locals, code_length233code_size + // code2342 + // exception_table_length235(2+2+2+2) * exception_table_length + // exception_table2362 + // attributes_count237attr_size; // attributes238239write_attribute_name_index("Code");240write_u4(size);241write_u2(method->verifier_max_stack());242write_u2(method->max_locals());243write_u4(code_size);244copy_bytecodes(method, (unsigned char*)writeable_address(code_size));245write_u2(exception_table_length);246for (int index = 0; index < exception_table_length; index++) {247write_u2(exception_table.start_pc(index));248write_u2(exception_table.end_pc(index));249write_u2(exception_table.handler_pc(index));250write_u2(exception_table.catch_type_index(index));251}252write_u2(attr_count);253if (line_num_cnt != 0) {254write_line_number_table_attribute(method, line_num_cnt);255}256if (stackmap_len != 0) {257write_stackmap_table_attribute(method, stackmap_len);258}259if (local_variable_table_length != 0) {260write_local_variable_table_attribute(method, local_variable_table_length);261}262if (local_variable_type_table_length != 0) {263write_local_variable_type_table_attribute(method, local_variable_type_table_length);264}265}266267// Write Exceptions attribute268// JVMSpec| Exceptions_attribute {269// JVMSpec| u2 attribute_name_index;270// JVMSpec| u4 attribute_length;271// JVMSpec| u2 number_of_exceptions;272// JVMSpec| u2 exception_index_table[number_of_exceptions];273// JVMSpec| }274void JvmtiClassFileReconstituter::write_exceptions_attribute(ConstMethod* const_method) {275CheckedExceptionElement* checked_exceptions = const_method->checked_exceptions_start();276int checked_exceptions_length = const_method->checked_exceptions_length();277int size =2782 + // number_of_exceptions2792 * checked_exceptions_length; // exception_index_table280281write_attribute_name_index("Exceptions");282write_u4(size);283write_u2(checked_exceptions_length);284for (int index = 0; index < checked_exceptions_length; index++) {285write_u2(checked_exceptions[index].class_cp_index);286}287}288289// Write SourceFile attribute290// JVMSpec| SourceFile_attribute {291// JVMSpec| u2 attribute_name_index;292// JVMSpec| u4 attribute_length;293// JVMSpec| u2 sourcefile_index;294// JVMSpec| }295void JvmtiClassFileReconstituter::write_source_file_attribute() {296assert(ik()->source_file_name() != NULL, "caller must check");297298write_attribute_name_index("SourceFile");299write_u4(2); // always length 2300write_u2(symbol_to_cpool_index(ik()->source_file_name()));301}302303// Write SourceDebugExtension attribute304// JSR45| SourceDebugExtension_attribute {305// JSR45| u2 attribute_name_index;306// JSR45| u4 attribute_length;307// JSR45| u1 debug_extension[attribute_length];308// JSR45| }309void JvmtiClassFileReconstituter::write_source_debug_extension_attribute() {310assert(ik()->source_debug_extension() != NULL, "caller must check");311312write_attribute_name_index("SourceDebugExtension");313int len = (int)strlen(ik()->source_debug_extension());314write_u4(len);315u1* ext = (u1*)ik()->source_debug_extension();316for (int i=0; i<len; i++) {317write_u1(ext[i]);318}319}320321// Write (generic) Signature attribute322// JVMSpec| Signature_attribute {323// JVMSpec| u2 attribute_name_index;324// JVMSpec| u4 attribute_length;325// JVMSpec| u2 signature_index;326// JVMSpec| }327void JvmtiClassFileReconstituter::write_signature_attribute(u2 generic_signature_index) {328write_attribute_name_index("Signature");329write_u4(2); // always length 2330write_u2(generic_signature_index);331}332333// Compute the number of entries in the InnerClasses attribute334u2 JvmtiClassFileReconstituter::inner_classes_attribute_length() {335InnerClassesIterator iter(ik());336return iter.length();337}338339// Write an annotation attribute. The VM stores them in raw form, so all we need340// to do is add the attrubute name and fill in the length.341// JSR202| *Annotations_attribute {342// JSR202| u2 attribute_name_index;343// JSR202| u4 attribute_length;344// JSR202| ...345// JSR202| }346void JvmtiClassFileReconstituter::write_annotations_attribute(const char* attr_name,347AnnotationArray* annos) {348u4 length = annos->length();349write_attribute_name_index(attr_name);350write_u4(length);351memcpy(writeable_address(length), annos->adr_at(0), length);352}353354// BootstrapMethods_attribute {355// u2 attribute_name_index;356// u4 attribute_length;357// u2 num_bootstrap_methods;358// { u2 bootstrap_method_ref;359// u2 num_bootstrap_arguments;360// u2 bootstrap_arguments[num_bootstrap_arguments];361// } bootstrap_methods[num_bootstrap_methods];362// }363void JvmtiClassFileReconstituter::write_bootstrapmethod_attribute() {364Array<u2>* operands = cpool()->operands();365write_attribute_name_index("BootstrapMethods");366int num_bootstrap_methods = ConstantPool::operand_array_length(operands);367368// calculate length of attribute369int length = sizeof(u2); // num_bootstrap_methods370for (int n = 0; n < num_bootstrap_methods; n++) {371u2 num_bootstrap_arguments = cpool()->operand_argument_count_at(n);372length += sizeof(u2); // bootstrap_method_ref373length += sizeof(u2); // num_bootstrap_arguments374length += sizeof(u2) * num_bootstrap_arguments; // bootstrap_arguments[num_bootstrap_arguments]375}376write_u4(length);377378// write attribute379write_u2(num_bootstrap_methods);380for (int n = 0; n < num_bootstrap_methods; n++) {381u2 bootstrap_method_ref = cpool()->operand_bootstrap_method_ref_index_at(n);382u2 num_bootstrap_arguments = cpool()->operand_argument_count_at(n);383write_u2(bootstrap_method_ref);384write_u2(num_bootstrap_arguments);385for (int arg = 0; arg < num_bootstrap_arguments; arg++) {386u2 bootstrap_argument = cpool()->operand_argument_index_at(n, arg);387write_u2(bootstrap_argument);388}389}390}391392// NestHost_attribute {393// u2 attribute_name_index;394// u4 attribute_length;395// u2 host_class_index;396// }397void JvmtiClassFileReconstituter::write_nest_host_attribute() {398int length = sizeof(u2);399int host_class_index = ik()->nest_host_index();400401write_attribute_name_index("NestHost");402write_u4(length);403write_u2(host_class_index);404}405406// NestMembers_attribute {407// u2 attribute_name_index;408// u4 attribute_length;409// u2 number_of_classes;410// u2 classes[number_of_classes];411// }412void JvmtiClassFileReconstituter::write_nest_members_attribute() {413Array<u2>* nest_members = ik()->nest_members();414int number_of_classes = nest_members->length();415int length = sizeof(u2) * (1 + number_of_classes);416417write_attribute_name_index("NestMembers");418write_u4(length);419write_u2(number_of_classes);420for (int i = 0; i < number_of_classes; i++) {421u2 class_cp_index = nest_members->at(i);422write_u2(class_cp_index);423}424}425426// PermittedSubclasses {427// u2 attribute_name_index;428// u4 attribute_length;429// u2 number_of_classes;430// u2 classes[number_of_classes];431// }432void JvmtiClassFileReconstituter::write_permitted_subclasses_attribute() {433Array<u2>* permitted_subclasses = ik()->permitted_subclasses();434int number_of_classes = permitted_subclasses->length();435int length = sizeof(u2) * (1 + number_of_classes); // '1 +' is for number_of_classes field436437write_attribute_name_index("PermittedSubclasses");438write_u4(length);439write_u2(number_of_classes);440for (int i = 0; i < number_of_classes; i++) {441u2 class_cp_index = permitted_subclasses->at(i);442write_u2(class_cp_index);443}444}445446// Record {447// u2 attribute_name_index;448// u4 attribute_length;449// u2 components_count;450// component_info components[components_count];451// }452// component_info {453// u2 name_index;454// u2 descriptor_index455// u2 attributes_count;456// attribute_info_attributes[attributes_count];457// }458void JvmtiClassFileReconstituter::write_record_attribute() {459Array<RecordComponent*>* components = ik()->record_components();460int number_of_components = components->length();461462// Each component has a u2 for name, descr, attribute count463int length = sizeof(u2) + (sizeof(u2) * 3 * number_of_components);464for (int x = 0; x < number_of_components; x++) {465RecordComponent* component = components->at(x);466if (component->generic_signature_index() != 0) {467length += 8; // Signature attribute size468assert(component->attributes_count() > 0, "Bad component attributes count");469}470if (component->annotations() != NULL) {471length += 6 + component->annotations()->length();472}473if (component->type_annotations() != NULL) {474length += 6 + component->type_annotations()->length();475}476}477478write_attribute_name_index("Record");479write_u4(length);480write_u2(number_of_components);481for (int i = 0; i < number_of_components; i++) {482RecordComponent* component = components->at(i);483write_u2(component->name_index());484write_u2(component->descriptor_index());485write_u2(component->attributes_count());486if (component->generic_signature_index() != 0) {487write_signature_attribute(component->generic_signature_index());488}489if (component->annotations() != NULL) {490write_annotations_attribute("RuntimeVisibleAnnotations", component->annotations());491}492if (component->type_annotations() != NULL) {493write_annotations_attribute("RuntimeVisibleTypeAnnotations", component->type_annotations());494}495}496}497498// Write InnerClasses attribute499// JVMSpec| InnerClasses_attribute {500// JVMSpec| u2 attribute_name_index;501// JVMSpec| u4 attribute_length;502// JVMSpec| u2 number_of_classes;503// JVMSpec| { u2 inner_class_info_index;504// JVMSpec| u2 outer_class_info_index;505// JVMSpec| u2 inner_name_index;506// JVMSpec| u2 inner_class_access_flags;507// JVMSpec| } classes[number_of_classes];508// JVMSpec| }509void JvmtiClassFileReconstituter::write_inner_classes_attribute(int length) {510InnerClassesIterator iter(ik());511guarantee(iter.length() != 0 && iter.length() == length,512"caller must check");513u2 entry_count = length / InstanceKlass::inner_class_next_offset;514u4 size = 2 + entry_count * (2+2+2+2);515516write_attribute_name_index("InnerClasses");517write_u4(size);518write_u2(entry_count);519for (; !iter.done(); iter.next()) {520write_u2(iter.inner_class_info_index());521write_u2(iter.outer_class_info_index());522write_u2(iter.inner_name_index());523write_u2(iter.inner_access_flags());524}525}526527// Write Synthetic attribute528// JVMSpec| Synthetic_attribute {529// JVMSpec| u2 attribute_name_index;530// JVMSpec| u4 attribute_length;531// JVMSpec| }532void JvmtiClassFileReconstituter::write_synthetic_attribute() {533write_attribute_name_index("Synthetic");534write_u4(0); //length always zero535}536537// Compute size of LineNumberTable538u2 JvmtiClassFileReconstituter::line_number_table_entries(const methodHandle& method) {539// The line number table is compressed so we don't know how big it is until decompressed.540// Decompression is really fast so we just do it twice.541u2 num_entries = 0;542CompressedLineNumberReadStream stream(method->compressed_linenumber_table());543while (stream.read_pair()) {544num_entries++;545}546return num_entries;547}548549// Write LineNumberTable attribute550// JVMSpec| LineNumberTable_attribute {551// JVMSpec| u2 attribute_name_index;552// JVMSpec| u4 attribute_length;553// JVMSpec| u2 line_number_table_length;554// JVMSpec| { u2 start_pc;555// JVMSpec| u2 line_number;556// JVMSpec| } line_number_table[line_number_table_length];557// JVMSpec| }558void JvmtiClassFileReconstituter::write_line_number_table_attribute(const methodHandle& method,559u2 num_entries) {560561write_attribute_name_index("LineNumberTable");562write_u4(2 + num_entries * (2 + 2));563write_u2(num_entries);564565CompressedLineNumberReadStream stream(method->compressed_linenumber_table());566while (stream.read_pair()) {567write_u2(stream.bci());568write_u2(stream.line());569}570}571572// Write LocalVariableTable attribute573// JVMSpec| LocalVariableTable_attribute {574// JVMSpec| u2 attribute_name_index;575// JVMSpec| u4 attribute_length;576// JVMSpec| u2 local_variable_table_length;577// JVMSpec| { u2 start_pc;578// JVMSpec| u2 length;579// JVMSpec| u2 name_index;580// JVMSpec| u2 descriptor_index;581// JVMSpec| u2 index;582// JVMSpec| } local_variable_table[local_variable_table_length];583// JVMSpec| }584void JvmtiClassFileReconstituter::write_local_variable_table_attribute(const methodHandle& method, u2 num_entries) {585write_attribute_name_index("LocalVariableTable");586write_u4(2 + num_entries * (2 + 2 + 2 + 2 + 2));587write_u2(num_entries);588589assert(method->localvariable_table_length() == num_entries, "just checking");590591LocalVariableTableElement *elem = method->localvariable_table_start();592for (int j=0; j<method->localvariable_table_length(); j++) {593write_u2(elem->start_bci);594write_u2(elem->length);595write_u2(elem->name_cp_index);596write_u2(elem->descriptor_cp_index);597write_u2(elem->slot);598elem++;599}600}601602// Write LocalVariableTypeTable attribute603// JVMSpec| LocalVariableTypeTable_attribute {604// JVMSpec| u2 attribute_name_index;605// JVMSpec| u4 attribute_length;606// JVMSpec| u2 local_variable_type_table_length;607// JVMSpec| { u2 start_pc;608// JVMSpec| u2 length;609// JVMSpec| u2 name_index;610// JVMSpec| u2 signature_index;611// JVMSpec| u2 index;612// JVMSpec| } local_variable_type_table[local_variable_type_table_length];613// JVMSpec| }614void JvmtiClassFileReconstituter::write_local_variable_type_table_attribute(const methodHandle& method, u2 num_entries) {615write_attribute_name_index("LocalVariableTypeTable");616write_u4(2 + num_entries * (2 + 2 + 2 + 2 + 2));617write_u2(num_entries);618619LocalVariableTableElement *elem = method->localvariable_table_start();620for (int j=0; j<method->localvariable_table_length(); j++) {621if (elem->signature_cp_index > 0) {622// Local variable has a generic signature - write LVTT attribute entry623write_u2(elem->start_bci);624write_u2(elem->length);625write_u2(elem->name_cp_index);626write_u2(elem->signature_cp_index);627write_u2(elem->slot);628num_entries--;629}630elem++;631}632assert(num_entries == 0, "just checking");633}634635// Write stack map table attribute636// JSR-202| StackMapTable_attribute {637// JSR-202| u2 attribute_name_index;638// JSR-202| u4 attribute_length;639// JSR-202| u2 number_of_entries;640// JSR-202| stack_map_frame_entries[number_of_entries];641// JSR-202| }642void JvmtiClassFileReconstituter::write_stackmap_table_attribute(const methodHandle& method,643int stackmap_len) {644645write_attribute_name_index("StackMapTable");646write_u4(stackmap_len);647memcpy(648writeable_address(stackmap_len),649(void*)(method->stackmap_data()->adr_at(0)),650stackmap_len);651}652653// Write one method_info structure654// JVMSpec| method_info {655// JVMSpec| u2 access_flags;656// JVMSpec| u2 name_index;657// JVMSpec| u2 descriptor_index;658// JVMSpec| u2 attributes_count;659// JVMSpec| attribute_info attributes[attributes_count];660// JVMSpec| }661void JvmtiClassFileReconstituter::write_method_info(const methodHandle& method) {662AccessFlags access_flags = method->access_flags();663ConstMethod* const_method = method->constMethod();664u2 generic_signature_index = const_method->generic_signature_index();665AnnotationArray* anno = method->annotations();666AnnotationArray* param_anno = method->parameter_annotations();667AnnotationArray* default_anno = method->annotation_default();668AnnotationArray* type_anno = method->type_annotations();669670// skip generated default interface methods671if (method->is_overpass()) {672return;673}674675write_u2(access_flags.get_flags() & JVM_RECOGNIZED_METHOD_MODIFIERS);676write_u2(const_method->name_index());677write_u2(const_method->signature_index());678679// write attributes in the same order javac does, so we can test with byte for680// byte comparison681int attr_count = 0;682if (const_method->code_size() != 0) {683++attr_count; // has Code attribute684}685if (const_method->has_checked_exceptions()) {686++attr_count; // has Exceptions attribute687}688if (default_anno != NULL) {689++attr_count; // has AnnotationDefault attribute690}691// Deprecated attribute would go here692if (access_flags.is_synthetic()) { // FIXME693// ++attr_count;694}695if (generic_signature_index != 0) {696++attr_count;697}698if (anno != NULL) {699++attr_count; // has RuntimeVisibleAnnotations attribute700}701if (param_anno != NULL) {702++attr_count; // has RuntimeVisibleParameterAnnotations attribute703}704if (type_anno != NULL) {705++attr_count; // has RuntimeVisibleTypeAnnotations attribute706}707708write_u2(attr_count);709if (const_method->code_size() > 0) {710write_code_attribute(method);711}712if (const_method->has_checked_exceptions()) {713write_exceptions_attribute(const_method);714}715if (default_anno != NULL) {716write_annotations_attribute("AnnotationDefault", default_anno);717}718// Deprecated attribute would go here719if (access_flags.is_synthetic()) {720// write_synthetic_attribute();721}722if (generic_signature_index != 0) {723write_signature_attribute(generic_signature_index);724}725if (anno != NULL) {726write_annotations_attribute("RuntimeVisibleAnnotations", anno);727}728if (param_anno != NULL) {729write_annotations_attribute("RuntimeVisibleParameterAnnotations", param_anno);730}731if (type_anno != NULL) {732write_annotations_attribute("RuntimeVisibleTypeAnnotations", type_anno);733}734}735736// Write the class attributes portion of ClassFile structure737// JVMSpec| u2 attributes_count;738// JVMSpec| attribute_info attributes[attributes_count];739void JvmtiClassFileReconstituter::write_class_attributes() {740u2 inner_classes_length = inner_classes_attribute_length();741Symbol* generic_signature = ik()->generic_signature();742AnnotationArray* anno = ik()->class_annotations();743AnnotationArray* type_anno = ik()->class_type_annotations();744745int attr_count = 0;746if (generic_signature != NULL) {747++attr_count;748}749if (ik()->source_file_name() != NULL) {750++attr_count;751}752if (ik()->source_debug_extension() != NULL) {753++attr_count;754}755if (inner_classes_length > 0) {756++attr_count;757}758if (anno != NULL) {759++attr_count; // has RuntimeVisibleAnnotations attribute760}761if (type_anno != NULL) {762++attr_count; // has RuntimeVisibleTypeAnnotations attribute763}764if (cpool()->operands() != NULL) {765++attr_count;766}767if (ik()->nest_host_index() != 0) {768++attr_count;769}770if (ik()->nest_members() != Universe::the_empty_short_array()) {771++attr_count;772}773if (ik()->permitted_subclasses() != Universe::the_empty_short_array()) {774++attr_count;775}776if (ik()->record_components() != NULL) {777++attr_count;778}779780write_u2(attr_count);781782if (generic_signature != NULL) {783write_signature_attribute(symbol_to_cpool_index(generic_signature));784}785if (ik()->source_file_name() != NULL) {786write_source_file_attribute();787}788if (ik()->source_debug_extension() != NULL) {789write_source_debug_extension_attribute();790}791if (anno != NULL) {792write_annotations_attribute("RuntimeVisibleAnnotations", anno);793}794if (type_anno != NULL) {795write_annotations_attribute("RuntimeVisibleTypeAnnotations", type_anno);796}797if (ik()->nest_host_index() != 0) {798write_nest_host_attribute();799}800if (ik()->nest_members() != Universe::the_empty_short_array()) {801write_nest_members_attribute();802}803if (ik()->permitted_subclasses() != Universe::the_empty_short_array()) {804write_permitted_subclasses_attribute();805}806if (ik()->record_components() != NULL) {807write_record_attribute();808}809if (cpool()->operands() != NULL) {810write_bootstrapmethod_attribute();811}812if (inner_classes_length > 0) {813write_inner_classes_attribute(inner_classes_length);814}815}816817// Write the method information portion of ClassFile structure818// JVMSpec| u2 methods_count;819// JVMSpec| method_info methods[methods_count];820void JvmtiClassFileReconstituter::write_method_infos() {821HandleMark hm(thread());822Array<Method*>* methods = ik()->methods();823int num_methods = methods->length();824int num_overpass = 0;825826// count the generated default interface methods827// these will not be re-created by write_method_info828// and should not be included in the total count829for (int index = 0; index < num_methods; index++) {830Method* method = methods->at(index);831if (method->is_overpass()) {832num_overpass++;833}834}835836write_u2(num_methods - num_overpass);837if (JvmtiExport::can_maintain_original_method_order()) {838int index;839int original_index;840intArray method_order(num_methods, num_methods, 0);841842// invert the method order mapping843for (index = 0; index < num_methods; index++) {844original_index = ik()->method_ordering()->at(index);845assert(original_index >= 0 && original_index < num_methods,846"invalid original method index");847method_order.at_put(original_index, index);848}849850// write in original order851for (original_index = 0; original_index < num_methods; original_index++) {852index = method_order.at(original_index);853methodHandle method(thread(), methods->at(index));854write_method_info(method);855}856} else {857// method order not preserved just dump the method infos858for (int index = 0; index < num_methods; index++) {859methodHandle method(thread(), methods->at(index));860write_method_info(method);861}862}863}864865void JvmtiClassFileReconstituter::write_class_file_format() {866ReallocMark();867868// JVMSpec| ClassFile {869// JVMSpec| u4 magic;870write_u4(0xCAFEBABE);871872// JVMSpec| u2 minor_version;873// JVMSpec| u2 major_version;874write_u2(ik()->minor_version());875u2 major = ik()->major_version();876write_u2(major);877878// JVMSpec| u2 constant_pool_count;879// JVMSpec| cp_info constant_pool[constant_pool_count-1];880write_u2(cpool()->length());881copy_cpool_bytes(writeable_address(cpool_size()));882883// JVMSpec| u2 access_flags;884write_u2(ik()->access_flags().get_flags() & JVM_RECOGNIZED_CLASS_MODIFIERS);885886// JVMSpec| u2 this_class;887// JVMSpec| u2 super_class;888write_u2(class_symbol_to_cpool_index(ik()->name()));889Klass* super_class = ik()->super();890write_u2(super_class == NULL? 0 : // zero for java.lang.Object891class_symbol_to_cpool_index(super_class->name()));892893// JVMSpec| u2 interfaces_count;894// JVMSpec| u2 interfaces[interfaces_count];895Array<InstanceKlass*>* interfaces = ik()->local_interfaces();896int num_interfaces = interfaces->length();897write_u2(num_interfaces);898for (int index = 0; index < num_interfaces; index++) {899HandleMark hm(thread());900InstanceKlass* iik = interfaces->at(index);901write_u2(class_symbol_to_cpool_index(iik->name()));902}903904// JVMSpec| u2 fields_count;905// JVMSpec| field_info fields[fields_count];906write_field_infos();907908// JVMSpec| u2 methods_count;909// JVMSpec| method_info methods[methods_count];910write_method_infos();911912// JVMSpec| u2 attributes_count;913// JVMSpec| attribute_info attributes[attributes_count];914// JVMSpec| } /* end ClassFile 8?915write_class_attributes();916}917918address JvmtiClassFileReconstituter::writeable_address(size_t size) {919size_t used_size = _buffer_ptr - _buffer;920if (size + used_size >= _buffer_size) {921// compute the new buffer size: must be at least twice as big as before922// plus whatever new is being used; then convert to nice clean block boundary923size_t new_buffer_size = (size + _buffer_size*2 + 1) / initial_buffer_size924* initial_buffer_size;925926// VM goes belly-up if the memory isn't available, so cannot do OOM processing927_buffer = REALLOC_RESOURCE_ARRAY(u1, _buffer, _buffer_size, new_buffer_size);928_buffer_size = new_buffer_size;929_buffer_ptr = _buffer + used_size;930}931u1* ret_ptr = _buffer_ptr;932_buffer_ptr += size;933return ret_ptr;934}935936void JvmtiClassFileReconstituter::write_attribute_name_index(const char* name) {937TempNewSymbol sym = SymbolTable::probe(name, (int)strlen(name));938assert(sym != NULL, "attribute name symbol not found");939u2 attr_name_index = symbol_to_cpool_index(sym);940assert(attr_name_index != 0, "attribute name symbol not in constant pool");941write_u2(attr_name_index);942}943944void JvmtiClassFileReconstituter::write_u1(u1 x) {945*writeable_address(1) = x;946}947948void JvmtiClassFileReconstituter::write_u2(u2 x) {949Bytes::put_Java_u2(writeable_address(2), x);950}951952void JvmtiClassFileReconstituter::write_u4(u4 x) {953Bytes::put_Java_u4(writeable_address(4), x);954}955956void JvmtiClassFileReconstituter::write_u8(u8 x) {957Bytes::put_Java_u8(writeable_address(8), x);958}959960void JvmtiClassFileReconstituter::copy_bytecodes(const methodHandle& mh,961unsigned char* bytecodes) {962// use a BytecodeStream to iterate over the bytecodes. JVM/fast bytecodes963// and the breakpoint bytecode are converted to their original bytecodes.964965BytecodeStream bs(mh);966967unsigned char* p = bytecodes;968Bytecodes::Code code;969bool is_rewritten = mh->method_holder()->is_rewritten();970971while ((code = bs.next()) >= 0) {972assert(Bytecodes::is_java_code(code), "sanity check");973assert(code != Bytecodes::_breakpoint, "sanity check");974975// length of bytecode (mnemonic + operands)976address bcp = bs.bcp();977int len = bs.instruction_size();978assert(len > 0, "length must be > 0");979980// copy the bytecodes981*p = (unsigned char) (bs.is_wide()? Bytecodes::_wide : code);982if (len > 1) {983memcpy(p+1, bcp+1, len-1);984}985986// During linking the get/put and invoke instructions are rewritten987// with an index into the constant pool cache. The original constant988// pool index must be returned to caller. Rewrite the index.989if (is_rewritten && len > 1) {990bool is_wide = false;991switch (code) {992case Bytecodes::_getstatic : // fall through993case Bytecodes::_putstatic : // fall through994case Bytecodes::_getfield : // fall through995case Bytecodes::_putfield : // fall through996case Bytecodes::_invokevirtual : // fall through997case Bytecodes::_invokespecial : // fall through998case Bytecodes::_invokestatic : // fall through999case Bytecodes::_invokedynamic : // fall through1000case Bytecodes::_invokeinterface : {1001assert(len == 3 ||1002(code == Bytecodes::_invokeinterface && len == 5) ||1003(code == Bytecodes::_invokedynamic && len == 5),1004"sanity check");10051006int cpci = Bytes::get_native_u2(bcp+1);1007bool is_invokedynamic = (code == Bytecodes::_invokedynamic);1008ConstantPoolCacheEntry* entry;1009if (is_invokedynamic) {1010cpci = Bytes::get_native_u4(bcp+1);1011entry = mh->constants()->invokedynamic_cp_cache_entry_at(cpci);1012} else {1013// cache cannot be pre-fetched since some classes won't have it yet1014entry = mh->constants()->cache()->entry_at(cpci);1015}1016int i = entry->constant_pool_index();1017assert(i < mh->constants()->length(), "sanity check");1018Bytes::put_Java_u2((address)(p+1), (u2)i); // java byte ordering1019if (is_invokedynamic) *(p+3) = *(p+4) = 0;1020break;1021}1022case Bytecodes::_ldc_w:1023is_wide = true; // fall through1024case Bytecodes::_ldc: {1025if (bs.raw_code() == Bytecodes::_fast_aldc || bs.raw_code() == Bytecodes::_fast_aldc_w) {1026int cpci = is_wide ? Bytes::get_native_u2(bcp+1) : (u1)(*(bcp+1));1027int i = mh->constants()->object_to_cp_index(cpci);1028assert(i < mh->constants()->length(), "sanity check");1029if (is_wide) {1030Bytes::put_Java_u2((address)(p+1), (u2)i); // java byte ordering1031} else {1032*(p+1) = (u1)i;1033}1034}1035break;1036}1037default:1038break;1039}1040}10411042p += len;1043}1044}104510461047