##有请志愿者java类和他的字节码
##java类
public class OtherClass {
public static int CONSTANT_O=9876;
public int o=1234;
public void dddd()
{
String dddd = "dddd";
//System.out.println(dddd);
System.out.println(dddd+CONSTANT_O);
}
}
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ByteCodeTest {
private int insert=678;
public static void main(String[] args) throws Exception {
ByteCodeTest byteCodeTest = new ByteCodeTest();
Method method = ByteCodeTest.class.getDeclaredMethod("testYYM", int.class, int.class);
Object result = method.invoke(byteCodeTest, 1,2);
System.in.read();
}
public int testYYM(int a, int b) throws Exception {
OtherClass otherClass = new OtherClass();
otherClass.dddd();
Field field = otherClass.getClass().getDeclaredField("CONSTANT_O");
field.setAccessible(true);
System.out.println(field.get(null));
int c = 0;
while(a>b) {
c = a-b;
}
c=c+1+this.insert;
return c;
}
}
##字节码
yym@yym:~/debug-java$ javap -v OtherClass.class
Classfile /home/yym/debug-java/OtherClass.class
Last modified Oct. 30, 2024; size 973 bytes
MD5 checksum a3f3d17f189c4662028e11e233580936
Compiled from "OtherClass.java"
public class OtherClass
minor version: 0
major version: 55
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #8 // OtherClass
super_class: #9 // java/lang/Object
interfaces: 0, fields: 2, methods: 3, attributes: 3
Constant pool:
#1 = Methodref #9.#21 // java/lang/Object."<init>":()V
#2 = Fieldref #8.#22 // OtherClass.o:I
#3 = String #17 // dddd
#4 = Fieldref #23.#24 // java/lang/System.out:Ljava/io/PrintStream;
#5 = Fieldref #8.#25 // OtherClass.CONSTANT_O:I
#6 = InvokeDynamic #0:#29 // #0:makeConcatWithConstants:(Ljava/lang/String;I)Ljava/lang/String;
#7 = Methodref #30.#31 // java/io/PrintStream.println:(Ljava/lang/String;)V
#8 = Class #32 // OtherClass
#9 = Class #33 // java/lang/Object
#10 = Utf8 CONSTANT_O
#11 = Utf8 I
#12 = Utf8 o
#13 = Utf8 <init>
#14 = Utf8 ()V
#15 = Utf8 Code
#16 = Utf8 LineNumberTable
#17 = Utf8 dddd
#18 = Utf8 <clinit>
#19 = Utf8 SourceFile
#20 = Utf8 OtherClass.java
#21 = NameAndType #13:#14 // "<init>":()V
#22 = NameAndType #12:#11 // o:I
#23 = Class #34 // java/lang/System
#24 = NameAndType #35:#36 // out:Ljava/io/PrintStream;
#25 = NameAndType #10:#11 // CONSTANT_O:I
#26 = Utf8 BootstrapMethods
#27 = MethodHandle 6:#37 // REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
#28 = String #38 // \u0001\u0001
#29 = NameAndType #39:#40 // makeConcatWithConstants:(Ljava/lang/String;I)Ljava/lang/String;
#30 = Class #41 // java/io/PrintStream
#31 = NameAndType #42:#43 // println:(Ljava/lang/String;)V
#32 = Utf8 OtherClass
#33 = Utf8 java/lang/Object
#34 = Utf8 java/lang/System
#35 = Utf8 out
#36 = Utf8 Ljava/io/PrintStream;
#37 = Methodref #44.#45 // java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
#38 = Utf8 \u0001\u0001
#39 = Utf8 makeConcatWithConstants
#40 = Utf8 (Ljava/lang/String;I)Ljava/lang/String;
#41 = Utf8 java/io/PrintStream
#42 = Utf8 println
#43 = Utf8 (Ljava/lang/String;)V
#44 = Class #46 // java/lang/invoke/StringConcatFactory
#45 = NameAndType #39:#50 // makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
#46 = Utf8 java/lang/invoke/StringConcatFactory
#47 = Class #52 // java/lang/invoke/MethodHandles$Lookup
#48 = Utf8 Lookup
#49 = Utf8 InnerClasses
#50 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
#51 = Class #53 // java/lang/invoke/MethodHandles
#52 = Utf8 java/lang/invoke/MethodHandles$Lookup
#53 = Utf8 java/lang/invoke/MethodHandles
{
public static int CONSTANT_O;
descriptor: I
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
public int o;
descriptor: I
flags: (0x0001) ACC_PUBLIC
public OtherClass();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: sipush 1234
8: putfield #2 // Field o:I
11: return
LineNumberTable:
line 1: 0
line 4: 4
public void dddd();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=3, locals=2, args_size=1
0: ldc #3 // String dddd
2: astore_1
3: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
6: aload_1
7: getstatic #5 // Field CONSTANT_O:I
10: invokedynamic #6, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;I)Ljava/lang/String;
15: invokevirtual #7 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
18: return
LineNumberTable:
line 9: 0
line 11: 3
line 12: 18
static {};
descriptor: ()V
flags: (0x0008) ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: sipush 9876
3: putstatic #5 // Field CONSTANT_O:I
6: return
LineNumberTable:
line 3: 0
}
SourceFile: "OtherClass.java"
InnerClasses:
public static final #48= #47 of #51; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
0: #27 REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
Method arguments:
#28 \u0001\u0001
yym@yym:~/debug-java$ javap -v ByteCodeTest.class
Classfile /home/yym/debug-java/ByteCodeTest.class
Last modified Oct. 30, 2024; size 1497 bytes
MD5 checksum 4436ea007276698cc3c392c190653ffd
Compiled from "ByteCodeTest.java"
public class ByteCodeTest
minor version: 0
major version: 55
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #3 // ByteCodeTest
super_class: #9 // java/lang/Object
interfaces: 0, fields: 1, methods: 3, attributes: 1
Constant pool:
#1 = Methodref #9.#40 // java/lang/Object."<init>":()V
#2 = Fieldref #3.#41 // ByteCodeTest.insert:I
#3 = Class #42 // ByteCodeTest
#4 = Methodref #3.#40 // ByteCodeTest."<init>":()V
#5 = String #34 // testYYM
#6 = Class #43 // java/lang/Class
#7 = Fieldref #44.#45 // java/lang/Integer.TYPE:Ljava/lang/Class;
#8 = Methodref #6.#46 // java/lang/Class.getDeclaredMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
#9 = Class #47 // java/lang/Object
#10 = Methodref #44.#48 // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
#11 = Methodref #49.#50 // java/lang/reflect/Method.invoke:(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
#12 = Fieldref #51.#52 // java/lang/System.in:Ljava/io/InputStream;
#13 = Methodref #53.#54 // java/io/InputStream.read:()I
#14 = Class #55 // OtherClass
#15 = Methodref #14.#40 // OtherClass."<init>":()V
#16 = Methodref #14.#56 // OtherClass.dddd:()V
#17 = Methodref #9.#57 // java/lang/Object.getClass:()Ljava/lang/Class;
#18 = String #58 // CONSTANT_O
#19 = Methodref #6.#59 // java/lang/Class.getDeclaredField:(Ljava/lang/String;)Ljava/lang/reflect/Field;
#20 = Methodref #37.#60 // java/lang/reflect/Field.setAccessible:(Z)V
#21 = Fieldref #51.#61 // java/lang/System.out:Ljava/io/PrintStream;
#22 = Methodref #37.#62 // java/lang/reflect/Field.get:(Ljava/lang/Object;)Ljava/lang/Object;
#23 = Methodref #63.#64 // java/io/PrintStream.println:(Ljava/lang/Object;)V
#24 = Utf8 insert
#25 = Utf8 I
#26 = Utf8 <init>
#27 = Utf8 ()V
#28 = Utf8 Code
#29 = Utf8 LineNumberTable
#30 = Utf8 main
#31 = Utf8 ([Ljava/lang/String;)V
#32 = Utf8 Exceptions
#33 = Class #65 // java/lang/Exception
#34 = Utf8 testYYM
#35 = Utf8 (II)I
#36 = Utf8 StackMapTable
#37 = Class #66 // java/lang/reflect/Field
#38 = Utf8 SourceFile
#39 = Utf8 ByteCodeTest.java
#40 = NameAndType #26:#27 // "<init>":()V
#41 = NameAndType #24:#25 // insert:I
#42 = Utf8 ByteCodeTest
#43 = Utf8 java/lang/Class
#44 = Class #67 // java/lang/Integer
#45 = NameAndType #68:#69 // TYPE:Ljava/lang/Class;
#46 = NameAndType #70:#71 // getDeclaredMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
#47 = Utf8 java/lang/Object
#48 = NameAndType #72:#73 // valueOf:(I)Ljava/lang/Integer;
#49 = Class #74 // java/lang/reflect/Method
#50 = NameAndType #75:#76 // invoke:(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
#51 = Class #77 // java/lang/System
#52 = NameAndType #78:#79 // in:Ljava/io/InputStream;
#53 = Class #80 // java/io/InputStream
#54 = NameAndType #81:#82 // read:()I
#55 = Utf8 OtherClass
#56 = NameAndType #83:#27 // dddd:()V
#57 = NameAndType #84:#85 // getClass:()Ljava/lang/Class;
#58 = Utf8 CONSTANT_O
#59 = NameAndType #86:#87 // getDeclaredField:(Ljava/lang/String;)Ljava/lang/reflect/Field;
#60 = NameAndType #88:#89 // setAccessible:(Z)V
#61 = NameAndType #90:#91 // out:Ljava/io/PrintStream;
#62 = NameAndType #92:#93 // get:(Ljava/lang/Object;)Ljava/lang/Object;
#63 = Class #94 // java/io/PrintStream
#64 = NameAndType #95:#96 // println:(Ljava/lang/Object;)V
#65 = Utf8 java/lang/Exception
#66 = Utf8 java/lang/reflect/Field
#67 = Utf8 java/lang/Integer
#68 = Utf8 TYPE
#69 = Utf8 Ljava/lang/Class;
#70 = Utf8 getDeclaredMethod
#71 = Utf8 (Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
#72 = Utf8 valueOf
#73 = Utf8 (I)Ljava/lang/Integer;
#74 = Utf8 java/lang/reflect/Method
#75 = Utf8 invoke
#76 = Utf8 (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
#77 = Utf8 java/lang/System
#78 = Utf8 in
#79 = Utf8 Ljava/io/InputStream;
#80 = Utf8 java/io/InputStream
#81 = Utf8 read
#82 = Utf8 ()I
#83 = Utf8 dddd
#84 = Utf8 getClass
#85 = Utf8 ()Ljava/lang/Class;
#86 = Utf8 getDeclaredField
#87 = Utf8 (Ljava/lang/String;)Ljava/lang/reflect/Field;
#88 = Utf8 setAccessible
#89 = Utf8 (Z)V
#90 = Utf8 out
#91 = Utf8 Ljava/io/PrintStream;
#92 = Utf8 get
#93 = Utf8 (Ljava/lang/Object;)Ljava/lang/Object;
#94 = Utf8 java/io/PrintStream
#95 = Utf8 println
#96 = Utf8 (Ljava/lang/Object;)V
{
public ByteCodeTest();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: sipush 678
8: putfield #2 // Field insert:I
11: return
LineNumberTable:
line 4: 0
line 6: 4
public static void main(java.lang.String[]) throws java.lang.Exception;
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=6, locals=4, args_size=1
0: new #3 // class ByteCodeTest
3: dup
4: invokespecial #4 // Method "<init>":()V
7: astore_1
8: ldc #3 // class ByteCodeTest
10: ldc #5 // String testYYM
12: iconst_2
13: anewarray #6 // class java/lang/Class
16: dup
17: iconst_0
18: getstatic #7 // Field java/lang/Integer.TYPE:Ljava/lang/Class;
21: aastore
22: dup
23: iconst_1
24: getstatic #7 // Field java/lang/Integer.TYPE:Ljava/lang/Class;
27: aastore
28: invokevirtual #8 // Method java/lang/Class.getDeclaredMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
31: astore_2
32: aload_2
33: aload_1
34: iconst_2
35: anewarray #9 // class java/lang/Object
38: dup
39: iconst_0
40: iconst_1
41: invokestatic #10 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
44: aastore
45: dup
46: iconst_1
47: iconst_2
48: invokestatic #10 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
51: aastore
52: invokevirtual #11 // Method java/lang/reflect/Method.invoke:(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
55: astore_3
56: getstatic #12 // Field java/lang/System.in:Ljava/io/InputStream;
59: invokevirtual #13 // Method java/io/InputStream.read:()I
62: pop
63: return
LineNumberTable:
line 9: 0
line 10: 8
line 11: 32
line 12: 56
line 13: 63
Exceptions:
throws java.lang.Exception
public int testYYM(int, int) throws java.lang.Exception;
descriptor: (II)I
flags: (0x0001) ACC_PUBLIC
Code:
stack=3, locals=6, args_size=3
0: new #14 // class OtherClass
3: dup
4: invokespecial #15 // Method OtherClass."<init>":()V
7: astore_3
8: aload_3
9: invokevirtual #16 // Method OtherClass.dddd:()V
12: aload_3
13: invokevirtual #17 // Method java/lang/Object.getClass:()Ljava/lang/Class;
16: ldc #18 // String CONSTANT_O
18: invokevirtual #19 // Method java/lang/Class.getDeclaredField:(Ljava/lang/String;)Ljava/lang/reflect/Field;
21: astore 4
23: aload 4
25: iconst_1
26: invokevirtual #20 // Method java/lang/reflect/Field.setAccessible:(Z)V
29: getstatic #21 // Field java/lang/System.out:Ljava/io/PrintStream;
32: aload 4
34: aconst_null
35: invokevirtual #22 // Method java/lang/reflect/Field.get:(Ljava/lang/Object;)Ljava/lang/Object;
38: invokevirtual #23 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
41: iconst_0
42: istore 5
44: iload_1
45: iload_2
46: if_icmple 57
49: iload_1
50: iload_2
51: isub
52: istore 5
54: goto 44
57: iload 5
59: iconst_1
60: iadd
61: aload_0
62: getfield #2 // Field insert:I
65: iadd
66: istore 5
68: iload 5
70: ireturn
LineNumberTable:
line 16: 0
line 17: 8
line 18: 12
line 19: 23
line 20: 29
line 21: 41
line 22: 44
line 23: 49
line 25: 57
line 26: 68
StackMapTable: number_of_entries = 2
frame_type = 254 /* append */
offset_delta = 44
locals = [ class OtherClass, class java/lang/reflect/Field, int ]
frame_type = 12 /* same */
Exceptions:
throws java.lang.Exception
}
SourceFile: "ByteCodeTest.java"
##init方法字节码,那openjdk17 hotspot是怎么执行这个方法的呢?
查看testYYM方法字节码,new OtherClass对象,invokespecial调用init方法
0: new #14 // class OtherClass
4: invokespecial #15 // Method OtherClass."<init>":()V
public OtherClass();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: sipush 1234
8: putfield #2 // Field o:I
11: return
LineNumberTable:
line 1: 0
line 4: 4
##openjdk17 hotspot 调用init方法源码步骤
模版解释器解释指令Bytecodes::_invokespecial
InterpreterRuntime::resolve_invoke 找到// Method OtherClass."<init>":()V
##templateTable_x86.cpp文件
void TemplateTable::prepare_invoke(int byte_no,
Register method, // linked method (or i-klass)
Register index, // itable index, MethodType, etc.
Register recv, // if caller wants to see it
Register flags // if caller wants to test it
) {
// determine flags
const Bytecodes::Code code = bytecode();
const bool is_invokeinterface = code == Bytecodes::_invokeinterface;
const bool is_invokedynamic = code == Bytecodes::_invokedynamic;
const bool is_invokehandle = code == Bytecodes::_invokehandle;
const bool is_invokevirtual = code == Bytecodes::_invokevirtual;
const bool is_invokespecial = code == Bytecodes::_invokespecial;
const bool load_receiver = (recv != noreg);
const bool save_flags = (flags != noreg);
assert(load_receiver == (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic), "");
assert(save_flags == (is_invokeinterface || is_invokevirtual), "need flags for vfinal");
assert(flags == noreg || flags == rdx, "");
assert(recv == noreg || recv == rcx, "");
// setup registers & access constant pool cache
if (recv == noreg) recv = rcx;
if (flags == noreg) flags = rdx;
assert_different_registers(method, index, recv, flags);
// save 'interpreter return address'
__ save_bcp();
load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic);
// maybe push appendix to arguments (just before return address)
if (is_invokedynamic || is_invokehandle) {
Label L_no_push;
__ testl(flags, (1 << ConstantPoolCacheEntry::has_appendix_shift));
__ jcc(Assembler::zero, L_no_push);
// Push the appendix as a trailing parameter.
// This must be done before we get the receiver,
// since the parameter_size includes it.
__ push(rbx);
__ mov(rbx, index);
__ load_resolved_reference_at_index(index, rbx);
__ pop(rbx);
__ push(index); // push appendix (MethodType, CallSite, etc.)
__ bind(L_no_push);
}
// load receiver if needed (after appendix is pushed so parameter size is correct)
// Note: no return address pushed yet
if (load_receiver) {
__ movl(recv, flags);
__ andl(recv, ConstantPoolCacheEntry::parameter_size_mask);
const int no_return_pc_pushed_yet = -1; // argument slot correction before we push return address
const int receiver_is_at_end = -1; // back off one slot to get receiver
Address recv_addr = __ argument_address(recv, no_return_pc_pushed_yet + receiver_is_at_end);
__ movptr(recv, recv_addr);
__ verify_oop(recv);
}
if (save_flags) {
__ movl(rbcp, flags);
}
// compute return type
__ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);
// Make sure we don't need to mask flags after the above shift
ConstantPoolCacheEntry::verify_tos_state_shift();
// load return address
{
const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code);
ExternalAddress table(table_addr);
LP64_ONLY(__ lea(rscratch1, table));
LP64_ONLY(__ movptr(flags, Address(rscratch1, flags, Address::times_ptr)));
NOT_LP64(__ movptr(flags, ArrayAddress(table, Address(noreg, flags, Address::times_ptr))));
}
// push return address
__ push(flags);
// Restore flags value from the constant pool cache, and restore rsi
// for later null checks. r13 is the bytecode pointer
if (save_flags) {
__ movl(flags, rbcp);
__ restore_bcp();
}
}
void TemplateTable::load_invoke_cp_cache_entry(int byte_no,
Register method,
Register itable_index,
Register flags,
bool is_invokevirtual,
bool is_invokevfinal, /*unused*/
bool is_invokedynamic) {
// setup registers
const Register cache = rcx;
const Register index = rdx;
assert_different_registers(method, flags);
assert_different_registers(method, cache, index);
assert_different_registers(itable_index, flags);
assert_different_registers(itable_index, cache, index);
// determine constant pool cache field offsets
assert(is_invokevirtual == (byte_no == f2_byte), "is_invokevirtual flag redundant");
const int flags_offset = in_bytes(ConstantPoolCache::base_offset() +
ConstantPoolCacheEntry::flags_offset());
// access constant pool cache fields
const int index_offset = in_bytes(ConstantPoolCache::base_offset() +
ConstantPoolCacheEntry::f2_offset());
size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2));
resolve_cache_and_index(byte_no, cache, index, index_size);
__ load_resolved_method_at_index(byte_no, method, cache, index);
if (itable_index != noreg) {
// pick up itable or appendix index from f2 also:
__ movptr(itable_index, Address(cache, index, Address::times_ptr, index_offset));
}
__ movl(flags, Address(cache, index, Address::times_ptr, flags_offset));
}
void TemplateTable::resolve_cache_and_index(int byte_no,
Register cache,
Register index,
size_t index_size) {
const Register temp = rbx;
assert_different_registers(cache, index, temp);
Label L_clinit_barrier_slow;
Label resolved;
Bytecodes::Code code = bytecode();
switch (code) {
case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break;
case Bytecodes::_nofast_putfield: code = Bytecodes::_putfield; break;
default: break;
}
assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
__ get_cache_and_index_and_bytecode_at_bcp(cache, index, temp, byte_no, 1, index_size);
__ cmpl(temp, code); // have we resolved this bytecode?
__ jcc(Assembler::equal, resolved);
// resolve first time through
// Class initialization barrier slow path lands here as well.
__ bind(L_clinit_barrier_slow);
// std::cout << "@@@@yym%%%%" << "method begin" << "----begin" << std::endl;
address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
__ movl(temp, code);
__ call_VM(noreg, entry, temp);
// std::cout << "@@@@yym%%%%" << "method end" << "----end" << std::endl;
// Update registers with resolved info
__ get_cache_and_index_at_bcp(cache, index, 1, index_size);
__ bind(resolved);
// Class initialization barrier for static methods
if (VM_Version::supports_fast_class_init_checks() && bytecode() == Bytecodes::_invokestatic) {
const Register method = temp;
const Register klass = temp;
const Register thread = LP64_ONLY(r15_thread) NOT_LP64(noreg);
assert(thread != noreg, "x86_32 not supported");
__ load_resolved_method_at_index(byte_no, method, cache, index);
__ load_method_holder(klass, method);
__ clinit_barrier(klass, thread, NULL /*L_fast_path*/, &L_clinit_barrier_slow);
}
}
##interpreterRuntime.cpp文件
##找到OtherClass.<init>()V方法
void InterpreterRuntime::resolve_invoke(JavaThread* current, Bytecodes::Code bytecode) {
LastFrameAccessor last_frame(current);
// extract receiver from the outgoing argument list if necessary
Handle receiver(current, NULL);
if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface ||
bytecode == Bytecodes::_invokespecial) {
ResourceMark rm(current);
methodHandle m (current, last_frame.method());
Bytecode_invoke call(m, last_frame.bci());
Symbol* signature = call.signature();
receiver = Handle(current, last_frame.callee_receiver(signature));
assert(Universe::heap()->is_in_or_null(receiver()),
"sanity check");
assert(receiver.is_null() ||
!Universe::heap()->is_in(receiver->klass()),
"sanity check");
}
// resolve method
CallInfo info;
constantPoolHandle pool(current, last_frame.method()->constants());
methodHandle resolved_method;
{
JvmtiHideSingleStepping jhss(current);
JavaThread* THREAD = current; // For exception macros.
LinkResolver::resolve_invoke(info, receiver, pool,
last_frame.get_index_u2_cpcache(bytecode), bytecode,
CHECK);
if (JvmtiExport::can_hotswap_or_post_breakpoint() && info.resolved_method()->is_old()) {
resolved_method = methodHandle(current, info.resolved_method()->get_new_method());
} else {
resolved_method = methodHandle(current, info.resolved_method());
}
} // end JvmtiHideSingleStepping
// check if link resolution caused cpCache to be updated
ConstantPoolCacheEntry* cp_cache_entry = last_frame.cache_entry();
if (cp_cache_entry->is_resolved(bytecode)) return;
#ifdef ASSERT
if (bytecode == Bytecodes::_invokeinterface) {
if (resolved_method->method_holder() == vmClasses::Object_klass()) {
// NOTE: THIS IS A FIX FOR A CORNER CASE in the JVM spec
// (see also CallInfo::set_interface for details)
assert(info.call_kind() == CallInfo::vtable_call ||
info.call_kind() == CallInfo::direct_call, "");
assert(resolved_method->is_final() || info.has_vtable_index(),
"should have been set already");
} else if (!resolved_method->has_itable_index()) {
// Resolved something like CharSequence.toString. Use vtable not itable.
assert(info.call_kind() != CallInfo::itable_call, "");
} else {
// Setup itable entry
assert(info.call_kind() == CallInfo::itable_call, "");
int index = resolved_method->itable_index();
assert(info.itable_index() == index, "");
}
} else if (bytecode == Bytecodes::_invokespecial) {
assert(info.call_kind() == CallInfo::direct_call, "must be direct call");
} else {
assert(info.call_kind() == CallInfo::direct_call ||
info.call_kind() == CallInfo::vtable_call, "");
}
#endif
// Get sender and only set cpCache entry to resolved if it is not an
// interface. The receiver for invokespecial calls within interface
// methods must be checked for every call.
InstanceKlass* sender = pool->pool_holder();
switch (info.call_kind()) {
case CallInfo::direct_call:
cp_cache_entry->set_direct_call(
bytecode,
resolved_method,
sender->is_interface());
break;
case CallInfo::vtable_call:
cp_cache_entry->set_vtable_call(
bytecode,
resolved_method,
info.vtable_index());
break;
case CallInfo::itable_call:
cp_cache_entry->set_itable_call(
bytecode,
info.resolved_klass(),
resolved_method,
info.itable_index());
break;
default: ShouldNotReachHere();
}
}
##GDB调试