前言
之前在 hllvm 群组看到了这样的一篇文章, [讨论] 有关实例化的内存分布
呵呵 当时记录了一个 todo, 呵呵 这里就 跟一下 相关的代码吧
根据 fieldName 找给定的字段, 找到偏移, 然后 在更新给定的对象给定的偏移的数据吧
[todo] get_field, put_field 的相关字节码 可以看下
一下内容基于 jdk9 + lldb-1001.0.13.3(lldb调试部分)
测试用例
package com.hx.test06;
/**
* GetSetField
*
* @author Jerry.X.He
* @version 1.0
* @date 2020-06-07 09:17
*/
public class Test20GetSetField {
// identStr
private static Test20GetSetField staticInstance = new Test20GetSetField();
private static Test20GetSetField anotherStaticInstance = new Test20GetSetField();
private String identStr = "identStr";
int f01;
int f02;
int f03;
// Test20GetSetField
public static void main(String[] args) {
staticInstance = anotherStaticInstance;
staticInstance.f02 = 10;
int x = staticInstance.f02;
}
}
对应的字节码信息如下, 下面参照可能需要使用到
master:classes jerry$ javap -c com/hx/test06/Test20GetSetField.class
Compiled from "Test20GetSetField.java"
public class com.hx.test06.Test20GetSetField {
int f01;
int f02;
int f03;
public com.hx.test06.Test20GetSetField();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: ldc #2 // String identStr
7: putfield #3 // Field identStr:Ljava/lang/String;
10: return
public static void main(java.lang.String[]);
Code:
0: getstatic #4 // Field anotherStaticInstance:Lcom/hx/test06/Test20GetSetField;
3: putstatic #5 // Field staticInstance:Lcom/hx/test06/Test20GetSetField;
6: getstatic #5 // Field staticInstance:Lcom/hx/test06/Test20GetSetField;
9: bipush 10
11: putfield #6 // Field f02:I
14: getstatic #5 // Field staticInstance:Lcom/hx/test06/Test20GetSetField;
17: getfield #6 // Field f02:I
20: istore_1
21: return
static {};
Code:
0: new #7 // class com/hx/test06/Test20GetSetField
3: dup
4: invokespecial #8 // Method "<init>":()V
7: putstatic #5 // Field staticInstance:Lcom/hx/test06/Test20GetSetField;
10: new #7 // class com/hx/test06/Test20GetSetField
13: dup
14: invokespecial #8 // Method "<init>":()V
17: putstatic #4 // Field anotherStaticInstance:Lcom/hx/test06/Test20GetSetField;
20: return
}
getstatic
getstatic 的代码以及汇编
生成 getstatic 的相关代码如下
void TemplateTable::getstatic(int byte_no) {
getfield_or_static(byte_no, true);
}
void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteControl rc) {
transition(vtos, vtos);
const Register cache = rcx;
const Register index = rdx;
const Register obj = LP64_ONLY(c_rarg3) NOT_LP64(rcx);
const Register off = rbx;
const Register flags = rax;
const Register bc = LP64_ONLY(c_rarg3) NOT_LP64(rcx); // uses same reg as obj, so don't mix them
resolve_cache_and_index(byte_no, cache, index, sizeof(u2));
jvmti_post_field_access(cache, index, is_static, false);
load_field_cp_cache_entry(obj, cache, index, off, flags, is_static);
if (!is_static) pop_and_check_object(obj);
const Address field(obj, off, Address::times_1, 0*wordSize);
NOT_LP64(const Address hi(obj, off, Address::times_1, 1*wordSize));
Label Done, notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble;
__ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);
// Make sure we don't need to mask edx after the above shift
assert(btos == 0, "change code, btos != 0");
__ andl(flags, ConstantPoolCacheEntry::tos_state_mask);
__ jcc(Assembler::notZero, notByte);
// btos
__ load_signed_byte(rax, field);
__ push(btos);
// Rewrite bytecode to be faster
if (!is_static && rc == may_rewrite) {
patch_bytecode(Bytecodes::_fast_bgetfield, bc, rbx);
}
__ jmp(Done);
__ bind(notByte);
__ cmpl(flags, ztos);
__ jcc(Assembler::notEqual, notBool);
// ztos (same code as btos)
__ load_signed_byte(rax, field);
__ push(ztos);
// Rewrite bytecode to be faster
if (!is_static && rc == may_rewrite) {
// use btos rewriting, no truncating to t/f bit is needed for getfield.
patch_bytecode(Bytecodes::_fast_bgetfield, bc, rbx);
}
__ jmp(Done);
__ bind(notBool);
__ cmpl(flags, atos);
__ jcc(Assembler::notEqual, notObj);
// atos
__ load_heap_oop(rax, field);
__ push(atos);
if (!is_static && rc == may_rewrite) {
patch_bytecode(Bytecodes::_fast_agetfield, bc, rbx);
}
__ jmp(Done);
__ bind(notObj);
__ cmpl(flags, itos);
__ jcc(Assembler::notEqual, notInt);
// itos
__ movl(rax, field);
__ push(itos);
// Rewrite bytecode to be faster
if (!is_static && rc == may_rewrite) {
patch_bytecode(Bytecodes::_fast_igetfield, bc, rbx);
}
__ jmp(Done);
__ bind(notInt);
__ cmpl(flags, ctos);
__ jcc(Assembler::notEqual, notChar);
// ctos
__ load_unsigned_short(rax, field);
__ push(ctos);
// Rewrite bytecode to be faster
if (!is_static && rc == may_rewrite) {
patch_bytecode(Bytecodes::_fast_cgetfield, bc, rbx);
}
__ jmp(Done);
__ bind(notChar);
__ cmpl(flags, stos);
__ jcc(Assembler::notEqual, notShort);
// stos
__ load_signed_short(rax, field);
__ push(stos);
// Rewrite bytecode to be faster
if (!is_static && rc == may_rewrite) {
patch_bytecode(Bytecodes::_fast_sgetfield, bc, rbx);
}
__ jmp(Done);
__ bind(notShort);
__ cmpl(flags, ltos);
__ jcc(Assembler::notEqual, notLong);
// ltos
#ifndef _LP64
// Generate code as if volatile. There just aren't enough registers to
// save that information and this code is faster than the test.
__ fild_d(field); // Must load atomically
__ subptr(rsp,2*wordSize); // Make space for store
__ fistp_d(Address(rsp,0));
__ pop(rax);
__ pop(rdx);
#else
__ movq(rax, field);
#endif
__ push(ltos);
// Rewrite bytecode to be faster
LP64_ONLY(if (!is_static && rc == may_rewrite) patch_bytecode(Bytecodes::_fast_lgetfield, bc, rbx));
__ jmp(Done);
__ bind(notLong);
__ cmpl(flags, ftos);
__ jcc(Assembler::notEqual, notFloat);
// ftos
__ load_float(field);
__ push(ftos);
// Rewrite bytecode to be faster
if (!is_static && rc == may_rewrite) {
patch_bytecode(Bytecodes::_fast_fgetfield, bc, rbx);
}
__ jmp(Done);
__ bind(notFloat);
#ifdef ASSERT
__ cmpl(flags, dtos);
__ jcc(Assembler::notEqual, notDouble);
#endif
// dtos
__ load_double(field);
__ push(dtos);
// Rewrite bytecode to be faster
if (!is_static && rc == may_rewrite) {
patch_bytecode(Bytecodes::_fast_dgetfield, bc, rbx);
}
#ifdef ASSERT
__ jmp(Done);
__ bind(notDouble);
__ stop("Bad state");
#endif
__ bind(Done);
// [jk] not needed currently
// volatile_barrier(Assembler::Membar_mask_bits(Assembler::LoadLoad |
// Assembler::LoadStore));
}
getstatic 的汇编代码如下
----------------------------------------------------------------------
getstatic 178 getstatic [0x000000011ed91180, 0x000000011ed91580] 1024 bytes
0x000000011ed91180: push %rax
0x000000011ed91181: jmpq 0x000000011ed911bf
0x000000011ed91186: sub $0x8,%rsp
0x000000011ed9118a: vmovss %xmm0,(%rsp)
0x000000011ed9118f: jmpq 0x000000011ed911bf
0x000000011ed91194: sub $0x10,%rsp
0x000000011ed91198: vmovsd %xmm0,(%rsp)
0x000000011ed9119d: jmpq 0x000000011ed911bf
0x000000011ed911a2: sub $0x10,%rsp
0x000000011ed911a6: mov %rax,(%rsp)
0x000000011ed911aa: movabs $0x0,%r10
0x000000011ed911b4: mov %r10,0x8(%rsp)
0x000000011ed911b9: jmpq 0x000000011ed911bf
0x000000011ed911be: push %rax
// resolve_cache_and_index
0x000000011ed911bf: movzwl 0x1(%r13),%edx
0x000000011ed911c4: mov -0x30(%rbp),%rcx
0x000000011ed911c8: shl $0x2,%edx
0x000000011ed911cb: mov 0x10(%rcx,%rdx,8),%ebx
0x000000011ed911cf: shr $0x10,%ebx
0x000000011ed911d2: and $0xff,%ebx
0x000000011ed911d8: cmp $0xb2,%ebx
0x000000011ed911de: je 0x000000011ed9131d
0x000000011ed911e4: mov $0xb2,%ebx
0x000000011ed911e9: callq 0x000000011ed911f3
0x000000011ed911ee: jmpq 0x000000011ed91311
0x000000011ed911f3: mov %rbx,%rsi
0x000000011ed911f6: lea 0x8(%rsp),%rax
0x000000011ed911fb: mov %r13,-0x40(%rbp)
0x000000011ed911ff: mov %r15,%rdi
0x000000011ed91202: mov %rbp,0x208(%r15)
0x000000011ed91209: mov %rax,0x1f8(%r15)
0x000000011ed91210: test $0xf,%esp
0x000000011ed91216: je 0x000000011ed9122e
0x000000011ed9121c: sub $0x8,%rsp
0x000000011ed91220: callq 0x000000010c99b988 = InterpreterRuntime::resolve_from_cache(JavaThread*, Bytecodes::Code)
0x000000011ed91225: add $0x8,%rsp
0x000000011ed91229: jmpq 0x000000011ed91233
0x000000011ed9122e: callq 0x000000010c99b988 = InterpreterRuntime::resolve_from_cache(JavaThread*, Bytecodes::Code)
0x000000011ed91233: movabs $0x0,%r10
0x000000011ed9123d: mov %r10,0x1f8(%r15)
0x000000011ed91244: movabs $0x0,%r10
0x000000011ed9124e: mov %r10,0x208(%r15)
0x000000011ed91255: movabs $0x0,%r10
0x000000011ed9125f: mov %r10,0x200(%r15)
0x000000011ed91266: mov 0x324(%r15),%edi
0x000000011ed9126d: test $0x1,%edi
0x000000011ed91273: je 0x000000011ed912aa
0x000000011ed91279: test $0x2,%edi
0x000000011ed9127f: jne 0x000000011ed912aa
0x000000011ed91285: test $0xf,%esp
0x000000011ed9128b: je 0x000000011ed912a3
0x000000011ed91291: sub $0x8,%rsp
0x000000011ed91295: callq 0x000000010c997002 = TemplateInterpreter::remove_activation_preserving_args_entry()
0x000000011ed9129a: add $0x8,%rsp
0x000000011ed9129e: jmpq 0x000000011ed912a8
0x000000011ed912a3: callq 0x000000010c997002 = TemplateInterpreter::remove_activation_preserving_args_entry()
0x000000011ed912a8: jmpq *%rax
0x000000011ed912aa: mov 0x3c8(%r15),%rdi
0x000000011ed912b1: test %rdi,%rdi
0x000000011ed912b4: je 0x000000011ed912f5
0x000000011ed912ba: mov 0x6c(%rdi),%edi
0x000000011ed912bd: cmp $0x1,%edi
0x000000011ed912c0: jne 0x000000011ed912f5
0x000000011ed912c6: mov 0x3c8(%r15),%rdi
0x000000011ed912cd: mov 0x70(%rdi),%edi
0x000000011ed912d0: test $0xf,%esp
0x000000011ed912d6: je 0x000000011ed912ee
0x000000011ed912dc: sub $0x8,%rsp
0x000000011ed912e0: callq 0x000000010c997012 = TemplateInterpreter::remove_activation_early_entry(TosState)
0x000000011ed912e5: add $0x8,%rsp
0x000000011ed912e9: jmpq 0x000000011ed912f3
0x000000011ed912ee: callq 0x000000010c997012 = TemplateInterpreter::remove_activation_early_entry(TosState)
0x000000011ed912f3: jmpq *%rax
0x000000011ed912f5: cmpq $0x0,0x8(%r15)
0x000000011ed912fd: je 0x000000011ed91308
0x000000011ed91303: jmpq 0x000000011ed61a00
0x000000011ed91308: mov -0x40(%rbp),%r13
0x000000011ed9130c: mov -0x38(%rbp),%r14
0x000000011ed91310: retq
0x000000011ed91311: movzwl 0x1(%r13),%edx
0x000000011ed91316: mov -0x30(%rbp),%rcx
0x000000011ed9131a: shl $0x2,%edx
// jvmti_post_field_access
0x000000011ed9131d: mov -0x11e5a46b(%rip),%eax # 0x000000010cf36eb8 = JvmtiExport::_field_access_count
0x000000011ed91323: test %eax,%eax
0x000000011ed91325: je 0x000000011ed9146f
0x000000011ed9132b: add $0x10,%rcx
0x000000011ed9132f: shl $0x3,%edx
0x000000011ed91332: add %rdx,%rcx
0x000000011ed91335: xor %rax,%rax
0x000000011ed91338: callq 0x000000011ed91342
0x000000011ed9133d: jmpq 0x000000011ed91463
0x000000011ed91342: mov %rcx,%rdx
0x000000011ed91345: mov %rax,%rsi
0x000000011ed91348: lea 0x8(%rsp),%rax
0x000000011ed9134d: mov %r13,-0x40(%rbp)
0x000000011ed91351: mov %r15,%rdi
0x000000011ed91354: mov %rbp,0x208(%r15)
0x000000011ed9135b: mov %rax,0x1f8(%r15)
0x000000011ed91362: test $0xf,%esp
0x000000011ed91368: je 0x000000011ed91380
0x000000011ed9136e: sub $0x8,%rsp
0x000000011ed91372: callq 0x000000010c99bfd6 = InterpreterRuntime::post_field_access(JavaThread*, oopDesc*, ConstantPoolCacheEntry*)
0x000000011ed91377: add $0x8,%rsp
0x000000011ed9137b: jmpq 0x000000011ed91385
0x000000011ed91380: callq 0x000000010c99bfd6 = InterpreterRuntime::post_field_access(JavaThread*, oopDesc*, ConstantPoolCacheEntry*)
0x000000011ed91385: movabs $0x0,%r10
0x000000011ed9138f: mov %r10,0x1f8(%r15)
0x000000011ed91396: movabs $0x0,%r10
0x000000011ed913a0: mov %r10,0x208(%r15)
0x000000011ed913a7: movabs $0x0,%r10
0x000000011ed913b1: mov %r10,0x200(%r15)
0x000000011ed913b8: mov 0x324(%r15),%edi
0x000000011ed913bf: test $0x1,%edi
0x000000011ed913c5: je 0x000000011ed913fc
0x000000011ed913cb: test $0x2,%edi
0x000000011ed913d1: jne 0x000000011ed913fc
0x000000011ed913d7: test $0xf,%esp
0x000000011ed913dd: je 0x000000011ed913f5
0x000000011ed913e3: sub $0x8,%rsp
0x000000011ed913e7: callq 0x000000010c997002 = TemplateInterpreter::remove_activation_preserving_args_entry()
0x000000011ed913ec: add $0x8,%rsp
0x000000011ed913f0: jmpq 0x000000011ed913fa
0x000000011ed913f5: callq 0x000000010c997002 = TemplateInterpreter::remove_activation_preserving_args_entry()
0x000000011ed913fa: jmpq *%rax
0x000000011ed913fc: mov 0x3c8(%r15),%rdi
0x000000011ed91403: test %rdi,%rdi
0x000000011ed91406: je 0x000000011ed91447
0x000000011ed9140c: mov 0x6c(%rdi),%edi
0x000000011ed9140f: cmp $0x1,%edi
0x000000011ed91412: jne 0x000000011ed91447
0x000000011ed91418: mov 0x3c8(%r15),%rdi
0x000000011ed9141f: mov 0x70(%rdi),%edi
0x000000011ed91422: test $0xf,%esp
0x000000011ed91428: je 0x000000011ed91440
0x000000011ed9142e: sub $0x8,%rsp
0x000000011ed91432: callq 0x000000010c997012 = TemplateInterpreter::remove_activation_early_entry(TosState)
0x000000011ed91437: add $0x8,%rsp
0x000000011ed9143b: jmpq 0x000000011ed91445
0x000000011ed91440: callq 0x000000010c997012 = TemplateInterpreter::remove_activation_early_entry(TosState)
0x000000011ed91445: jmpq *%rax
0x000000011ed91447: cmpq $0x0,0x8(%r15)
0x000000011ed9144f: je 0x000000011ed9145a
0x000000011ed91455: jmpq 0x000000011ed61a00
0x000000011ed9145a: mov -0x40(%rbp),%r13
0x000000011ed9145e: mov -0x38(%rbp),%r14
0x000000011ed91462: retq
// load_field_cp_cache_entry
0x000000011ed91463: movzwl 0x1(%r13),%edx
0x000000011ed91468: mov -0x30(%rbp),%rcx
0x000000011ed9146c: shl $0x2,%edx
0x000000011ed9146f: mov 0x20(%rcx,%rdx,8),%rbx
0x000000011ed91474: mov 0x28(%rcx,%rdx,8),%eax
0x000000011ed91478: mov 0x18(%rcx,%rdx,8),%rcx
0x000000011ed9147d: mov 0x68(%rcx),%rcx
0x000000011ed91481: shr $0x1c,%eax
// byte
0x000000011ed91484: and $0xf,%eax
0x000000011ed91487: jne 0x000000011ed91497
0x000000011ed9148d: movsbl (%rcx,%rbx,1),%eax
0x000000011ed91491: push %rax
0x000000011ed91492: jmpq 0x000000011ed9154b
// boolean
0x000000011ed91497: cmp $0x1,%eax
0x000000011ed9149a: jne 0x000000011ed914aa
0x000000011ed914a0: movsbl (%rcx,%rbx,1),%eax
0x000000011ed914a4: push %rax
0x000000011ed914a5: jmpq 0x000000011ed9154b
// object
0x000000011ed914aa: cmp $0x8,%eax
0x000000011ed914ad: jne 0x000000011ed914c0
0x000000011ed914b3: mov (%rcx,%rbx,1),%eax
0x000000011ed914b6: shl $0x3,%rax
0x000000011ed914ba: push %rax
0x000000011ed914bb: jmpq 0x000000011ed9154b
// int
0x000000011ed914c0: cmp $0x4,%eax
0x000000011ed914c3: jne 0x000000011ed914d2
0x000000011ed914c9: mov (%rcx,%rbx,1),%eax
0x000000011ed914cc: push %rax
0x000000011ed914cd: jmpq 0x000000011ed9154b
// char
0x000000011ed914d2: cmp $0x2,%eax
0x000000011ed914d5: jne 0x000000011ed914e5
0x000000011ed914db: movzwl (%rcx,%rbx,1),%eax
0x000000011ed914df: push %rax
0x000000011ed914e0: jmpq 0x000000011ed9154b
// short
0x000000011ed914e5: cmp $0x3,%eax
0x000000011ed914e8: jne 0x000000011ed914f8
0x000000011ed914ee: movswl (%rcx,%rbx,1),%eax
0x000000011ed914f2: push %rax
0x000000011ed914f3: jmpq 0x000000011ed9154b
// long
0x000000011ed914f8: cmp $0x5,%eax
0x000000011ed914fb: jne 0x000000011ed91521
0x000000011ed91501: mov (%rcx,%rbx,1),%rax
0x000000011ed91505: sub $0x10,%rsp
0x000000011ed91509: mov %rax,(%rsp)
0x000000011ed9150d: movabs $0x0,%r10
0x000000011ed91517: mov %r10,0x8(%rsp)
0x000000011ed9151c: jmpq 0x000000011ed9154b
// float
0x000000011ed91521: cmp $0x6,%eax
0x000000011ed91524: jne 0x000000011ed9153d
0x000000011ed9152a: vmovss (%rcx,%rbx,1),%xmm0
0x000000011ed9152f: sub $0x8,%rsp
0x000000011ed91533: vmovss %xmm0,(%rsp)
0x000000011ed91538: jmpq 0x000000011ed9154b
// double
0x000000011ed9153d: vmovsd (%rcx,%rbx,1),%xmm0
0x000000011ed91542: sub $0x10,%rsp
0x000000011ed91546: vmovsd %xmm0,(%rsp)
0x000000011ed9154b: movzbl 0x3(%r13),%ebx
0x000000011ed91550: add $0x3,%r13
0x000000011ed91554: movabs $0x10cf4c950,%r10
0x000000011ed9155e: jmpq *(%r10,%rbx,8)
0x000000011ed91562: nopw 0x0(%rax,%rax,1)
0x000000011ed91568: add %al,(%rax)
0x000000011ed9156a: add %al,(%rax)
0x000000011ed9156c: add %al,(%rax)
0x000000011ed9156e: add %al,(%rax)
0x000000011ed91570: add %al,(%rax)
0x000000011ed91572: add %al,(%rax)
0x000000011ed91574: add %al,(%rax)
0x000000011ed91576: add %al,(%rax)
0x000000011ed91578: add %al,(%rax)
0x000000011ed9157a: add %al,(%rax)
0x000000011ed9157c: add %al,(%rax)
0x000000011ed9157e: add %al,(%rax)
resolve_cache_and_index 的主要的作用是将解析 constantsPoolCache 中给定的字段的相关信息(所属类型, 字段索引, 字段偏移, 相关标记信息, 常量池信息)
load_field_cp_cache_entry 的主要作用是 加载字段对应的对象, 加载字段偏移
我们这里着重关注 getstatic 的数据处理部分, 也就是上面的 根据不同的数据类型, 加载字段, push 到栈顶
另外一点就是 到数据处理这里的时候, cx 存放的是字段对应的对象, bx 存放的是字段的偏移, 这两点信息 是我们待会儿的调试的需要注意的关键点
getstatic 基于 lldb 的调试
进入程序, 在 getstatic 的地方打上一个断点
(lldb) p _active_table._table[9][178]
(address) $0 = 0x00000001058495df "A\x0f\xb7U\x01H\x8bM??\U0000008b\\???\x10\x81??
(lldb) p _active_table._table[0][0]
(address) $1 = 0x0000000105830b9e "PA\x0f\xb6]\x01I??I\xbap\xb20\x04\x01"
(lldb) p _normal_table._table[0][0]
(address) $2 = 0x0000000105830b9e "PA\x0f\xb6]\x01I??I\xbap\xb20\x04\x01"
(lldb) p _safept_table._table[0][0]
(address) $3 = 0x00000001058252e0 "P?
(lldb) b 0x00000001058495df
Breakpoint 3: address = 0x00000001058495df
(lldb) c
Process 1964 resuming
Process 1964 stopped
* thread #5, stop reason = breakpoint 3.1
frame #0: 0x00000001058495df
-> 0x1058495df: movzwl 0x1(%r13), %edx
0x1058495e4: movq -0x30(%rbp), %rcx
0x1058495e8: shll $0x2, %edx
0x1058495eb: movl 0x10(%rcx,%rdx,8), %ebx
Target 0: (java) stopped.
(lldb) re r
General Purpose Registers:
rax = 0x0000700001f12648
rbx = 0x00000000000000b2
rcx = 0x0000000000000008
rdx = 0x0000000000000000
rdi = 0x0000000105000800
rsi = 0x0000000000000008
rbp = 0x0000700001f12690
rsp = 0x0000700001f12648
r8 = 0x0000000000002901
r9 = 0x0000000105000800
r10 = 0x000000010430b270 libjvm.dylib`TemplateInterpreter::_active_table + 18432
r11 = 0x0000000000000000
r12 = 0x0000000000000000
r13 = 0x000000011e46ef48
r14 = 0x0000700001f126a8
r15 = 0x0000000105000800
rip = 0x00000001058495df
rflags = 0x0000000000000246
cs = 0x000000000000002b
fs = 0x0000000000000000
gs = 0x0000000000000000
(lldb) x 0x000000011e46ef48
0x11e46ef48: b2 02 00 b3 03 00 b2 03 00 10 0a b5 04 00 b2 03 ?..?..?....?..?.
0x11e46ef58: 00 b4 04 00 3c b1 ff 00 2e 32 41 3a 00 00 00 00 .?..<??..2A:....
(lldb) x 0x0000700001f12648
0x700001f12648: 48 26 f1 01 00 70 00 00 48 ef 46 1e 01 00 00 00 H&?..p..H?F.....
0x700001f12658: a8 26 f1 01 00 70 00 00 88 f0 46 1e 01 00 00 00 ?&?..p...?F.....
(lldb) po ((ConstantPoolCache*)(0x011e46f088))->constant_pool()->print()
{constant pool}
- holder: 0x00000007c008fc30
- cache: 0x000000011e46f088
- resolved_references: 0x0000000747bb8160
- reference_map: 0x000000011e46f158
- 1 : Method : klass_index=9 name_and_type_index=33
- 2 : String : 'identStr'
- 3 : Field : klass_index=7 name_and_type_index=34
- 4 : Field : klass_index=7 name_and_type_index=35
- 5 : Field : klass_index=7 name_and_type_index=36
- 6 : Field : klass_index=7 name_and_type_index=37
- 7 : Class : 'com/hx/test06/Test20GetSetField' {0x00000007c008fc30}
- 8 : Method : klass_index=7 name_and_type_index=33
- 9 : Class : 'java/lang/Object' {0x00000007c0000f70}
- 10 : Utf8 : 'staticInstance'
- 11 : Utf8 : 'Lcom/hx/test06/Test20GetSetField;'
- 12 : Utf8 : 'anotherStaticInstance'
- 13 : Utf8 : 'identStr'
- 14 : Utf8 : 'Ljava/lang/String;'
- 15 : Utf8 : 'f01'
- 16 : Utf8 : 'I'
- 17 : Utf8 : 'f02'
- 18 : Utf8 : 'f03'
- 19 : Utf8 : '<init>'
- 20 : Utf8 : '()V'
- 21 : Utf8 : 'Code'
- 22 : Utf8 : 'LineNumberTable'
- 23 : Utf8 : 'LocalVariableTable'
- 24 : Utf8 : 'this'
- 25 : Utf8 : 'main'
- 26 : Utf8 : '([Ljava/lang/String;)V'
- 27 : Utf8 : 'args'
- 28 : Utf8 : '[Ljava/lang/String;'
- 29 : Utf8 : 'x'
- 30 : Utf8 : '<clinit>'
- 31 : Utf8 : 'SourceFile'
- 32 : Utf8 : 'Test20GetSetField.java'
- 33 : NameAndType : name_index=19 signature_index=20
- 34 : NameAndType : name_index=13 signature_index=14
- 35 : NameAndType : name_index=12 signature_index=11
- 36 : NameAndType : name_index=10 signature_index=11
- 37 : NameAndType : name_index=17 signature_index=16
- 38 : Utf8 : 'com/hx/test06/Test20GetSetField'
- 39 : Utf8 : 'java/lang/Object'
(lldb) p ((InstanceKlass*)0x00000007c008fc30)->java_mirror()->print()
java.lang.Class
{0x0000000747bb7fb0} - klass: 'java/lang/Class'
- ---- fields (total size 15 words):
- private volatile transient strict 'cachedConstructor' 'Ljava/lang/reflect/Constructor;' @12 NULL (0 0)
- private volatile transient strict 'newInstanceCallerCache' 'Ljava/lang/Class;' @16 NULL (0 e8f77007)
- private transient 'name' 'Ljava/lang/String;' @20 "com.hx.test06.Test20GetSetField"{0x0000000747bb8038} (e8f77007 e8fc0b37)
- private transient 'module' 'Ljava/lang/Module;' @24 a 'java/lang/Module'{0x0000000747e059b8} (e8fc0b37 e8fc0af7)
- private final 'classLoader' 'Ljava/lang/ClassLoader;' @28 a 'jdk/internal/loader/ClassLoaders$AppClassLoader'{0x0000000747e057b8} (e8fc0af7 e8f767c3)
- private transient 'packageName' 'Ljava/lang/String;' @32 "com.hx.test06"{0x0000000747bb3e18} (e8f767c3 0)
- private final strict 'componentType' 'Ljava/lang/Class;' @36 NULL (0 e8f77027)
- private volatile transient strict 'reflectionData' 'Ljava/lang/ref/SoftReference;' @40 a 'java/lang/ref/SoftReference'{0x0000000747bb8138} (e8f77027 0)
- private volatile transient 'genericInfo' 'Lsun/reflect/generics/repository/ClassRepository;' @44 NULL (0 0)
- private volatile transient strict 'enumConstants' '[Ljava/lang/Object;' @48 NULL (0 0)
- private volatile transient strict 'enumConstantDirectory' 'Ljava/util/Map;' @52 NULL (0 0)
- private volatile transient 'annotationData' 'Ljava/lang/Class$AnnotationData;' @56 NULL (0 0)
- private volatile transient 'annotationType' 'Lsun/reflect/annotation/AnnotationType;' @60 NULL (0 0)
- transient 'classValueMap' 'Ljava/lang/ClassValue$ClassValueMap;' @64 NULL (0 e8f76f31)
- private volatile transient 'classRedefinedCount' 'I' @96 0
- signature: Lcom/hx/test06/Test20GetSetField;
- fake entry for mirror: 'com/hx/test06/Test20GetSetField'
- fake entry for array: NULL
- fake entry for oop_size: 15
- fake entry for static_oop_field_count: 2
- private static 'staticInstance' 'Lcom/hx/test06/Test20GetSetField;' @112 a 'com/hx/test06/Test20GetSetField'{0x0000000747bb8390} (e8f77072 e8f7707c)
- private static 'anotherStaticInstance' 'Lcom/hx/test06/Test20GetSetField;' @116 a 'com/hx/test06/Test20GetSetField'{0x0000000747bb83e0} (e8f7707c 1)
(lldb)
打印当前的字节码相关信息, 可以定位到当前是在执行 getstatic
b2 02 00 b3 03 00 b2 03 00 10 0a
// 转换为字节码信息
getstatic #2 // Field anotherStaticInstance:Lcom/hx/test06/Test20GetSetField;
putstatic #3 // Field staticInstance:Lcom/hx/test06/Test20GetSetField;
getstatic #2 // Field staticInstance:Lcom/hx/test06/Test20GetSetField;
bipush 10
这里还顺便 输出了一下 Test20GetSetField 的常量池的信息, 以及 Test20GetSetField.class 的信息
然后在我们数据处理之前打上一个断点
(lldb) b 0x105849890
Breakpoint 4: address = 0x0000000105849890
(lldb) c
Process 1964 resuming
Process 1964 stopped
* thread #5, stop reason = breakpoint 4.1
frame #0: 0x0000000105849890
-> 0x105849890: jne 0x1058498a0
0x105849896: movsbl (%rcx,%rbx), %eax
0x10584989a: pushq %rax
0x10584989b: jmp 0x105849a61
Target 0: (java) stopped.
(lldb) re r
General Purpose Registers:
rax = 0x0000000000000008
rbx = 0x0000000000000074
rcx = 0x0000000747bb7fb0
rdx = 0x0000000000000008
rdi = 0x0000000105000800
rsi = 0x0000000000000008
rbp = 0x0000700001f12690
rsp = 0x0000700001f12648
r8 = 0x0000000000000000
r9 = 0x0000000100340790
r10 = 0x0000000000000000
r11 = 0x000000010034078c
r12 = 0x0000000000000000
r13 = 0x000000011e46ef48
r14 = 0x0000700001f126a8
r15 = 0x0000000105000800
rip = 0x0000000105849890
rflags = 0x0000000000000202
cs = 0x000000000000002b
fs = 0x0000000000000000
gs = 0x0000000000000000
可以发现此时 cx 是 0x0000000747bb7fb0 正是 Test20GetSetField.class
然后 bx 是 0x0000000000000074 = 116(十进制), 在 Test20GetSetField.class 的 oop 上面 偏移为 116 的数据是 anotherStaticInstance
到断点处 ax 存放的是 字段的类型(atos = 0x08)
然后我们来看一下 数据处理
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x00000001058498a0
-> 0x1058498a0: cmpl $0x1, %eax
0x1058498a3: jne 0x1058498b3
0x1058498a9: movsbl (%rcx,%rbx), %eax
0x1058498ad: pushq %rax
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x00000001058498a3
-> 0x1058498a3: jne 0x1058498b3
0x1058498a9: movsbl (%rcx,%rbx), %eax
0x1058498ad: pushq %rax
0x1058498ae: jmp 0x105849a61
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x00000001058498b3
-> 0x1058498b3: cmpl $0x8, %eax
0x1058498b6: jne 0x105849951
0x1058498bc: movl (%rcx,%rbx), %eax
0x1058498bf: pushq %r10
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x00000001058498b6
-> 0x1058498b6: jne 0x105849951
0x1058498bc: movl (%rcx,%rbx), %eax
0x1058498bf: pushq %r10
0x1058498c1: cmpq -0x15332d8(%rip), %r12 ; Universe::_narrow_ptrs_base
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x00000001058498bc
-> 0x1058498bc: movl (%rcx,%rbx), %eax
0x1058498bf: pushq %r10
0x1058498c1: cmpq -0x15332d8(%rip), %r12 ; Universe::_narrow_ptrs_base
0x1058498c8: je 0x105849945
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x00000001058498bf
-> 0x1058498bf: pushq %r10
0x1058498c1: cmpq -0x15332d8(%rip), %r12 ; Universe::_narrow_ptrs_base
0x1058498c8: je 0x105849945
0x1058498ce: movq %rsp, -0x28(%rsp)
Target 0: (java) stopped.
(lldb) re r
General Purpose Registers:
rax = 0x00000000e8f7707c
rbx = 0x0000000000000074
rcx = 0x0000000747bb7fb0
rdx = 0x0000000000000008
rdi = 0x0000000105000800
rsi = 0x0000000000000008
rbp = 0x0000700001f12690
rsp = 0x0000700001f12648
r8 = 0x0000000000000000
r9 = 0x0000000100340790
r10 = 0x0000000000000000
r11 = 0x000000010034078c
r12 = 0x0000000000000000
r13 = 0x000000011e46ef48
r14 = 0x0000700001f126a8
r15 = 0x0000000105000800
rip = 0x00000001058498bf
rflags = 0x0000000000000246
cs = 0x000000000000002b
fs = 0x0000000000000000
gs = 0x0000000000000000
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x00000001058498c1
-> 0x1058498c1: cmpq -0x15332d8(%rip), %r12 ; Universe::_narrow_ptrs_base
0x1058498c8: je 0x105849945
0x1058498ce: movq %rsp, -0x28(%rsp)
0x1058498d3: subq $0x80, %rsp
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x00000001058498c8
-> 0x1058498c8: je 0x105849945
0x1058498ce: movq %rsp, -0x28(%rsp)
0x1058498d3: subq $0x80, %rsp
0x1058498da: movq %rax, 0x78(%rsp)
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x0000000105849945
-> 0x105849945: popq %r10
0x105849947: shlq $0x3, %rax
0x10584994b: pushq %rax
0x10584994c: jmp 0x105849a61
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x0000000105849947
-> 0x105849947: shlq $0x3, %rax
0x10584994b: pushq %rax
0x10584994c: jmp 0x105849a61
0x105849951: cmpl $0x4, %eax
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x000000010584994b
-> 0x10584994b: pushq %rax
0x10584994c: jmp 0x105849a61
0x105849951: cmpl $0x4, %eax
0x105849954: jne 0x105849963
Target 0: (java) stopped.
(lldb) re r
General Purpose Registers:
rax = 0x0000000747bb83e0
rbx = 0x0000000000000074
rcx = 0x0000000747bb7fb0
rdx = 0x0000000000000008
rdi = 0x0000000105000800
rsi = 0x0000000000000008
rbp = 0x0000700001f12690
rsp = 0x0000700001f12648
r8 = 0x0000000000000000
r9 = 0x0000000100340790
r10 = 0x0000000000000000
r11 = 0x000000010034078c
r12 = 0x0000000000000000
r13 = 0x000000011e46ef48
r14 = 0x0000700001f126a8
r15 = 0x0000000105000800
rip = 0x000000010584994b
rflags = 0x0000000000000202
cs = 0x000000000000002b
fs = 0x0000000000000000
gs = 0x0000000000000000
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x000000010584994c
-> 0x10584994c: jmp 0x105849a61
0x105849951: cmpl $0x4, %eax
0x105849954: jne 0x105849963
0x10584995a: movl (%rcx,%rbx), %eax
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x0000000105849a61
-> 0x105849a61: movzbl 0x3(%r13), %ebx
0x105849a66: addq $0x3, %r13
0x105849a6a: movabsq $0x10430b270, %r10 ; imm = 0x10430B270
0x105849a74: jmpq *(%r10,%rbx,8)
Target 0: (java) stopped.
(lldb)
实际的调试过程中 会发现多了一段 r10 的相关的东西, 呵呵 但是不影响这里的逻辑
获取了 Test20GetSetField.class 上面存放的 anotherStaticInstance 的地址信息, 然后 恢复指针(<<3)
然后 压入表达式栈中
putstatic
putstatic 的代码以及汇编
生成 putstatic 的相关代码如下
void TemplateTable::putstatic(int byte_no) {
putfield_or_static(byte_no, true);
}
void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteControl rc) {
transition(vtos, vtos);
const Register cache = rcx;
const Register index = rdx;
const Register obj = rcx;
const Register off = rbx;
const Register flags = rax;
const Register bc = LP64_ONLY(c_rarg3) NOT_LP64(rcx);
resolve_cache_and_index(byte_no, cache, index, sizeof(u2));
jvmti_post_field_mod(cache, index, is_static);
load_field_cp_cache_entry(obj, cache, index, off, flags, is_static);
// [jk] not needed currently
// volatile_barrier(Assembler::Membar_mask_bits(Assembler::LoadStore |
// Assembler::StoreStore));
Label notVolatile, Done;
__ movl(rdx, flags);
__ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift);
__ andl(rdx, 0x1);
// field addresses
const Address field(obj, off, Address::times_1, 0*wordSize);
NOT_LP64( const Address hi(obj, off, Address::times_1, 1*wordSize);)
Label notByte, notBool, notInt, notShort, notChar,
notLong, notFloat, notObj, notDouble;
__ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);
assert(btos == 0, "change code, btos != 0");
__ andl(flags, ConstantPoolCacheEntry::tos_state_mask);
__ jcc(Assembler::notZero, notByte);
// btos
{
__ pop(btos);
if (!is_static) pop_and_check_object(obj);
__ movb(field, rax);
if (!is_static && rc == may_rewrite) {
patch_bytecode(Bytecodes::_fast_bputfield, bc, rbx, true, byte_no);
}
__ jmp(Done);
}
__ bind(notByte);
__ cmpl(flags, ztos);
__ jcc(Assembler::notEqual, notBool);
// ztos
{
__ pop(ztos);
if (!is_static) pop_and_check_object(obj);
__ andl(rax, 0x1);
__ movb(field, rax);
if (!is_static && rc == may_rewrite) {
patch_bytecode(Bytecodes::_fast_zputfield, bc, rbx, true, byte_no);
}
__ jmp(Done);
}
__ bind(notBool);
__ cmpl(flags, atos);
__ jcc(Assembler::notEqual, notObj);
// atos
{
__ pop(atos);
if (!is_static) pop_and_check_object(obj);
// Store into the field
do_oop_store(_masm, field, rax, _bs->kind(), false);
if (!is_static && rc == may_rewrite) {
patch_bytecode(Bytecodes::_fast_aputfield, bc, rbx, true, byte_no);
}
__ jmp(Done);
}
__ bind(notObj);
__ cmpl(flags, itos);
__ jcc(Assembler::notEqual, notInt);
// itos
{
__ pop(itos);
if (!is_static) pop_and_check_object(obj);
__ movl(field, rax);
if (!is_static && rc == may_rewrite) {
patch_bytecode(Bytecodes::_fast_iputfield, bc, rbx, true, byte_no);
}
__ jmp(Done);
}
__ bind(notInt);
__ cmpl(flags, ctos);
__ jcc(Assembler::notEqual, notChar);
// ctos
{
__ pop(ctos);
if (!is_static) pop_and_check_object(obj);
__ movw(field, rax);
if (!is_static && rc == may_rewrite) {
patch_bytecode(Bytecodes::_fast_cputfield, bc, rbx, true, byte_no);
}
__ jmp(Done);
}
__ bind(notChar);
__ cmpl(flags, stos);
__ jcc(Assembler::notEqual, notShort);
// stos
{
__ pop(stos);
if (!is_static) pop_and_check_object(obj);
__ movw(field, rax);
if (!is_static && rc == may_rewrite) {
patch_bytecode(Bytecodes::_fast_sputfield, bc, rbx, true, byte_no);
}
__ jmp(Done);
}
__ bind(notShort);
__ cmpl(flags, ltos);
__ jcc(Assembler::notEqual, notLong);
// ltos
#ifdef _LP64
{
__ pop(ltos);
if (!is_static) pop_and_check_object(obj);
__ movq(field, rax);
if (!is_static && rc == may_rewrite) {
patch_bytecode(Bytecodes::_fast_lputfield, bc, rbx, true, byte_no);
}
__ jmp(Done);
}
#else
{
Label notVolatileLong;
__ testl(rdx, rdx);
__ jcc(Assembler::zero, notVolatileLong);
__ pop(ltos); // overwrites rdx, do this after testing volatile.
if (!is_static) pop_and_check_object(obj);
// Replace with real volatile test
__ push(rdx);
__ push(rax); // Must update atomically with FIST
__ fild_d(Address(rsp,0)); // So load into FPU register
__ fistp_d(field); // and put into memory atomically
__ addptr(rsp, 2*wordSize);
// volatile_barrier();
volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad |
Assembler::StoreStore));
// Don't rewrite volatile version
__ jmp(notVolatile);
__ bind(notVolatileLong);
__ pop(ltos); // overwrites rdx
if (!is_static) pop_and_check_object(obj);
__ movptr(hi, rdx);
__ movptr(field, rax);
// Don't rewrite to _fast_lputfield for potential volatile case.
__ jmp(notVolatile);
}
#endif // _LP64
__ bind(notLong);
__ cmpl(flags, ftos);
__ jcc(Assembler::notEqual, notFloat);
// ftos
{
__ pop(ftos);
if (!is_static) pop_and_check_object(obj);
__ store_float(field);
if (!is_static && rc == may_rewrite) {
patch_bytecode(Bytecodes::_fast_fputfield, bc, rbx, true, byte_no);
}
__ jmp(Done);
}
__ bind(notFloat);
#ifdef ASSERT
__ cmpl(flags, dtos);
__ jcc(Assembler::notEqual, notDouble);
#endif
// dtos
{
__ pop(dtos);
if (!is_static) pop_and_check_object(obj);
__ store_double(field);
if (!is_static && rc == may_rewrite) {
patch_bytecode(Bytecodes::_fast_dputfield, bc, rbx, true, byte_no);
}
}
#ifdef ASSERT
__ jmp(Done);
__ bind(notDouble);
__ stop("Bad state");
#endif
__ bind(Done);
// Check for volatile store
__ testl(rdx, rdx);
__ jcc(Assembler::zero, notVolatile);
volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad |
Assembler::StoreStore));
__ bind(notVolatile);
}
putstatic 的汇编代码如下
----------------------------------------------------------------------
putstatic 179 putstatic [0x000000011ed915a0, 0x000000011ed91ae0] 1344 bytes
0x000000011ed915a0: push %rax
0x000000011ed915a1: jmpq 0x000000011ed915df
0x000000011ed915a6: sub $0x8,%rsp
0x000000011ed915aa: vmovss %xmm0,(%rsp)
0x000000011ed915af: jmpq 0x000000011ed915df
0x000000011ed915b4: sub $0x10,%rsp
0x000000011ed915b8: vmovsd %xmm0,(%rsp)
0x000000011ed915bd: jmpq 0x000000011ed915df
0x000000011ed915c2: sub $0x10,%rsp
0x000000011ed915c6: mov %rax,(%rsp)
0x000000011ed915ca: movabs $0x0,%r10
0x000000011ed915d4: mov %r10,0x8(%rsp)
0x000000011ed915d9: jmpq 0x000000011ed915df
0x000000011ed915de: push %rax
// resolve_cache_and_index
0x000000011ed915df: movzwl 0x1(%r13),%edx
0x000000011ed915e4: mov -0x30(%rbp),%rcx
0x000000011ed915e8: shl $0x2,%edx
0x000000011ed915eb: mov 0x10(%rcx,%rdx,8),%ebx
0x000000011ed915ef: shr $0x18,%ebx
0x000000011ed915f2: and $0xff,%ebx
0x000000011ed915f8: cmp $0xb3,%ebx
0x000000011ed915fe: je 0x000000011ed9173d
0x000000011ed91604: mov $0xb3,%ebx
0x000000011ed91609: callq 0x000000011ed91613
0x000000011ed9160e: jmpq 0x000000011ed91731
0x000000011ed91613: mov %rbx,%rsi
0x000000011ed91616: lea 0x8(%rsp),%rax
0x000000011ed9161b: mov %r13,-0x40(%rbp)
0x000000011ed9161f: mov %r15,%rdi
0x000000011ed91622: mov %rbp,0x208(%r15)
0x000000011ed91629: mov %rax,0x1f8(%r15)
0x000000011ed91630: test $0xf,%esp
0x000000011ed91636: je 0x000000011ed9164e
0x000000011ed9163c: sub $0x8,%rsp
0x000000011ed91640: callq 0x000000010c99b988 = InterpreterRuntime::resolve_from_cache(JavaThread*, Bytecodes::Code)
0x000000011ed91645: add $0x8,%rsp
0x000000011ed91649: jmpq 0x000000011ed91653
0x000000011ed9164e: callq 0x000000010c99b988 = InterpreterRuntime::resolve_from_cache(JavaThread*, Bytecodes::Code)
0x000000011ed91653: movabs $0x0,%r10
0x000000011ed9165d: mov %r10,0x1f8(%r15)
0x000000011ed91664: movabs $0x0,%r10
0x000000011ed9166e: mov %r10,0x208(%r15)
0x000000011ed91675: movabs $0x0,%r10
0x000000011ed9167f: mov %r10,0x200(%r15)
0x000000011ed91686: mov 0x324(%r15),%edi
0x000000011ed9168d: test $0x1,%edi
0x000000011ed91693: je 0x000000011ed916ca
0x000000011ed91699: test $0x2,%edi
0x000000011ed9169f: jne 0x000000011ed916ca
0x000000011ed916a5: test $0xf,%esp
0x000000011ed916ab: je 0x000000011ed916c3
0x000000011ed916b1: sub $0x8,%rsp
0x000000011ed916b5: callq 0x000000010c997002 = TemplateInterpreter::remove_activation_preserving_args_entry()
0x000000011ed916ba: add $0x8,%rsp
0x000000011ed916be: jmpq 0x000000011ed916c8
0x000000011ed916c3: callq 0x000000010c997002 = TemplateInterpreter::remove_activation_preserving_args_entry()
0x000000011ed916c8: jmpq *%rax
0x000000011ed916ca: mov 0x3c8(%r15),%rdi
0x000000011ed916d1: test %rdi,%rdi
0x000000011ed916d4: je 0x000000011ed91715
0x000000011ed916da: mov 0x6c(%rdi),%edi
0x000000011ed916dd: cmp $0x1,%edi
0x000000011ed916e0: jne 0x000000011ed91715
0x000000011ed916e6: mov 0x3c8(%r15),%rdi
0x000000011ed916ed: mov 0x70(%rdi),%edi
0x000000011ed916f0: test $0xf,%esp
0x000000011ed916f6: je 0x000000011ed9170e
0x000000011ed916fc: sub $0x8,%rsp
0x000000011ed91700: callq 0x000000010c997012 = TemplateInterpreter::remove_activation_early_entry(TosState)
0x000000011ed91705: add $0x8,%rsp
0x000000011ed91709: jmpq 0x000000011ed91713
0x000000011ed9170e: callq 0x000000010c997012 = TemplateInterpreter::remove_activation_early_entry(TosState)
0x000000011ed91713: jmpq *%rax
0x000000011ed91715: cmpq $0x0,0x8(%r15)
0x000000011ed9171d: je 0x000000011ed91728
0x000000011ed91723: jmpq 0x000000011ed61a00
0x000000011ed91728: mov -0x40(%rbp),%r13
0x000000011ed9172c: mov -0x38(%rbp),%r14
0x000000011ed91730: retq
0x000000011ed91731: movzwl 0x1(%r13),%edx
0x000000011ed91736: mov -0x30(%rbp),%rcx
0x000000011ed9173a: shl $0x2,%edx
// jvmti_post_field_access
0x000000011ed9173d: mov -0x11e5a887(%rip),%eax # 0x000000010cf36ebc = JvmtiExport::_field_modification_count
0x000000011ed91743: test %eax,%eax
0x000000011ed91745: je 0x000000011ed91899
0x000000011ed9174b: movzwl 0x1(%r13),%r10d
0x000000011ed91750: mov -0x30(%rbp),%rdx
0x000000011ed91754: shl $0x2,%r10d
0x000000011ed91758: xor %esi,%esi
0x000000011ed9175a: add $0x10,%rdx
0x000000011ed9175e: shl $0x3,%r10d
0x000000011ed91762: add %r10,%rdx
0x000000011ed91765: mov %rsp,%rcx
0x000000011ed91768: callq 0x000000011ed91772
0x000000011ed9176d: jmpq 0x000000011ed9188d
0x000000011ed91772: lea 0x8(%rsp),%rax
0x000000011ed91777: mov %r13,-0x40(%rbp)
0x000000011ed9177b: mov %r15,%rdi
0x000000011ed9177e: mov %rbp,0x208(%r15)
0x000000011ed91785: mov %rax,0x1f8(%r15)
0x000000011ed9178c: test $0xf,%esp
0x000000011ed91792: je 0x000000011ed917aa
0x000000011ed91798: sub $0x8,%rsp
0x000000011ed9179c: callq 0x000000010c99c0d8 = InterpreterRuntime::post_field_modification(JavaThread*, oopDesc*, ConstantPoolCacheEntry*, jvalue*)
0x000000011ed917a1: add $0x8,%rsp
0x000000011ed917a5: jmpq 0x000000011ed917af
0x000000011ed917aa: callq 0x000000010c99c0d8 = InterpreterRuntime::post_field_modification(JavaThread*, oopDesc*, ConstantPoolCacheEntry*, jvalue*)
0x000000011ed917af: movabs $0x0,%r10
0x000000011ed917b9: mov %r10,0x1f8(%r15)
0x000000011ed917c0: movabs $0x0,%r10
0x000000011ed917ca: mov %r10,0x208(%r15)
0x000000011ed917d1: movabs $0x0,%r10
0x000000011ed917db: mov %r10,0x200(%r15)
0x000000011ed917e2: mov 0x324(%r15),%edi
0x000000011ed917e9: test $0x1,%edi
0x000000011ed917ef: je 0x000000011ed91826
0x000000011ed917f5: test $0x2,%edi
0x000000011ed917fb: jne 0x000000011ed91826
0x000000011ed91801: test $0xf,%esp
0x000000011ed91807: je 0x000000011ed9181f
0x000000011ed9180d: sub $0x8,%rsp
0x000000011ed91811: callq 0x000000010c997002 = TemplateInterpreter::remove_activation_preserving_args_entry()
0x000000011ed91816: add $0x8,%rsp
0x000000011ed9181a: jmpq 0x000000011ed91824
0x000000011ed9181f: callq 0x000000010c997002 = TemplateInterpreter::remove_activation_preserving_args_entry()
0x000000011ed91824: jmpq *%rax
0x000000011ed91826: mov 0x3c8(%r15),%rdi
0x000000011ed9182d: test %rdi,%rdi
0x000000011ed91830: je 0x000000011ed91871
0x000000011ed91836: mov 0x6c(%rdi),%edi
0x000000011ed91839: cmp $0x1,%edi
0x000000011ed9183c: jne 0x000000011ed91871
0x000000011ed91842: mov 0x3c8(%r15),%rdi
0x000000011ed91849: mov 0x70(%rdi),%edi
0x000000011ed9184c: test $0xf,%esp
0x000000011ed91852: je 0x000000011ed9186a
0x000000011ed91858: sub $0x8,%rsp
0x000000011ed9185c: callq 0x000000010c997012 = TemplateInterpreter::remove_activation_early_entry(TosState)
0x000000011ed91861: add $0x8,%rsp
0x000000011ed91865: jmpq 0x000000011ed9186f
0x000000011ed9186a: callq 0x000000010c997012 = TemplateInterpreter::remove_activation_early_entry(TosState)
0x000000011ed9186f: jmpq *%rax
0x000000011ed91871: cmpq $0x0,0x8(%r15)
0x000000011ed91879: je 0x000000011ed91884
0x000000011ed9187f: jmpq 0x000000011ed61a00
0x000000011ed91884: mov -0x40(%rbp),%r13
0x000000011ed91888: mov -0x38(%rbp),%r14
0x000000011ed9188c: retq
// load_field_cp_cache_entry
0x000000011ed9188d: movzwl 0x1(%r13),%edx
0x000000011ed91892: mov -0x30(%rbp),%rcx
0x000000011ed91896: shl $0x2,%edx
0x000000011ed91899: mov 0x20(%rcx,%rdx,8),%rbx
0x000000011ed9189e: mov 0x28(%rcx,%rdx,8),%eax
0x000000011ed918a2: mov 0x18(%rcx,%rdx,8),%rcx
0x000000011ed918a7: mov 0x68(%rcx),%rcx
0x000000011ed918ab: mov %eax,%edx
0x000000011ed918ad: shr $0x15,%edx
0x000000011ed918b0: and $0x1,%edx
0x000000011ed918b3: shr $0x1c,%eax
// byte
0x000000011ed918b6: and $0xf,%eax
0x000000011ed918b9: jne 0x000000011ed918ce
0x000000011ed918bf: mov (%rsp),%eax
0x000000011ed918c2: add $0x8,%rsp
0x000000011ed918c6: mov %al,(%rcx,%rbx,1)
0x000000011ed918c9: jmpq 0x000000011ed91ab6
// boolean
0x000000011ed918ce: cmp $0x1,%eax
0x000000011ed918d1: jne 0x000000011ed918e9
0x000000011ed918d7: mov (%rsp),%eax
0x000000011ed918da: add $0x8,%rsp
0x000000011ed918de: and $0x1,%eax
0x000000011ed918e1: mov %al,(%rcx,%rbx,1)
0x000000011ed918e4: jmpq 0x000000011ed91ab6
// object
0x000000011ed918e9: cmp $0x8,%eax
0x000000011ed918ec: jne 0x000000011ed91a28
0x000000011ed918f2: pop %rax
0x000000011ed918f3: lea (%rcx,%rbx,1),%rdx
0x000000011ed918f7: cmpb $0x0,0x340(%r15)
0x000000011ed918ff: je 0x000000011ed9196f
0x000000011ed91905: mov (%rdx),%ebx
0x000000011ed91907: shl $0x3,%rbx
0x000000011ed9190b: cmp $0x0,%rbx
0x000000011ed9190f: je 0x000000011ed9196f
0x000000011ed91915: mov 0x350(%r15),%r8
0x000000011ed9191c: cmp $0x0,%r8
0x000000011ed91920: je 0x000000011ed91940
0x000000011ed91926: sub $0x8,%r8
0x000000011ed9192a: mov %r8,0x350(%r15)
0x000000011ed91931: add 0x348(%r15),%r8
0x000000011ed91938: mov %rbx,(%r8)
0x000000011ed9193b: jmpq 0x000000011ed9196f
0x000000011ed91940: push %rax
0x000000011ed91941: push %rdx
0x000000011ed91942: push %rbx
0x000000011ed91943: mov %r15,%rsi
0x000000011ed91946: mov %rbx,%rdi
0x000000011ed91949: test $0xf,%esp
0x000000011ed9194f: je 0x000000011ed91967
0x000000011ed91955: sub $0x8,%rsp
0x000000011ed91959: callq 0x000000010cc6aa7e = SharedRuntime::g1_wb_pre(oopDesc*, JavaThread*)
0x000000011ed9195e: add $0x8,%rsp
0x000000011ed91962: jmpq 0x000000011ed9196c
0x000000011ed91967: callq 0x000000010cc6aa7e = SharedRuntime::g1_wb_pre(oopDesc*, JavaThread*)
0x000000011ed9196c: pop %rbx
0x000000011ed9196d: pop %rdx
0x000000011ed9196e: pop %rax
0x000000011ed9196f: mov %rax,%rbx
0x000000011ed91972: shr $0x3,%rax
0x000000011ed91976: mov %eax,(%rdx)
0x000000011ed91978: mov %rdx,%r8
0x000000011ed9197b: xor %rbx,%r8
0x000000011ed9197e: shr $0x14,%r8
0x000000011ed91982: je 0x000000011ed91a23
0x000000011ed91988: cmp $0x0,%rbx
0x000000011ed9198c: je 0x000000011ed91a23
0x000000011ed91992: mov %rdx,%r8
0x000000011ed91995: shr $0x9,%r8
0x000000011ed91999: movabs $0x10ab16000,%rbx
0x000000011ed919a3: add %rbx,%r8
0x000000011ed919a6: cmpb $0x20,(%r8)
0x000000011ed919aa: je 0x000000011ed91a23
0x000000011ed919b0: lock addl $0x0,-0x40(%rsp)
0x000000011ed919b6: cmpb $0x0,(%r8)
0x000000011ed919ba: je 0x000000011ed91a23
0x000000011ed919c0: movb $0x0,(%r8)
0x000000011ed919c4: cmpl $0x0,0x388(%r15)
0x000000011ed919cf: je 0x000000011ed919f6
0x000000011ed919d5: subl $0x8,0x388(%r15)
0x000000011ed919dd: mov 0x380(%r15),%rbx
0x000000011ed919e4: movslq 0x388(%r15),%r10
0x000000011ed919eb: add %r10,%rbx
0x000000011ed919ee: mov %r8,(%rbx)
0x000000011ed919f1: jmpq 0x000000011ed91a23
0x000000011ed919f6: push %rdx
0x000000011ed919f7: push %rbx
0x000000011ed919f8: mov %r15,%rsi
0x000000011ed919fb: mov %r8,%rdi
0x000000011ed919fe: test $0xf,%esp
0x000000011ed91a04: je 0x000000011ed91a1c
0x000000011ed91a0a: sub $0x8,%rsp
0x000000011ed91a0e: callq 0x000000010cc6aaa8 = SharedRuntime::g1_wb_post(void*, JavaThread*)
0x000000011ed91a13: add $0x8,%rsp
0x000000011ed91a17: jmpq 0x000000011ed91a21
0x000000011ed91a1c: callq 0x000000010cc6aaa8 = SharedRuntime::g1_wb_post(void*, JavaThread*)
0x000000011ed91a21: pop %rbx
0x000000011ed91a22: pop %rdx
0x000000011ed91a23: jmpq 0x000000011ed91ab6
// int
0x000000011ed91a28: cmp $0x4,%eax
0x000000011ed91a2b: jne 0x000000011ed91a40
0x000000011ed91a31: mov (%rsp),%eax
0x000000011ed91a34: add $0x8,%rsp
0x000000011ed91a38: mov %eax,(%rcx,%rbx,1)
0x000000011ed91a3b: jmpq 0x000000011ed91ab6
// char
0x000000011ed91a40: cmp $0x2,%eax
0x000000011ed91a43: jne 0x000000011ed91a59
0x000000011ed91a49: mov (%rsp),%eax
0x000000011ed91a4c: add $0x8,%rsp
0x000000011ed91a50: mov %ax,(%rcx,%rbx,1)
0x000000011ed91a54: jmpq 0x000000011ed91ab6
// short
0x000000011ed91a59: cmp $0x3,%eax
0x000000011ed91a5c: jne 0x000000011ed91a72
0x000000011ed91a62: mov (%rsp),%eax
0x000000011ed91a65: add $0x8,%rsp
0x000000011ed91a69: mov %ax,(%rcx,%rbx,1)
0x000000011ed91a6d: jmpq 0x000000011ed91ab6
// long
0x000000011ed91a72: cmp $0x5,%eax
0x000000011ed91a75: jne 0x000000011ed91a8c
0x000000011ed91a7b: mov (%rsp),%rax
0x000000011ed91a7f: add $0x10,%rsp
0x000000011ed91a83: mov %rax,(%rcx,%rbx,1)
0x000000011ed91a87: jmpq 0x000000011ed91ab6
// float
0x000000011ed91a8c: cmp $0x6,%eax
0x000000011ed91a8f: jne 0x000000011ed91aa8
0x000000011ed91a95: vmovss (%rsp),%xmm0
0x000000011ed91a9a: add $0x8,%rsp
0x000000011ed91a9e: vmovss %xmm0,(%rcx,%rbx,1)
0x000000011ed91aa3: jmpq 0x000000011ed91ab6
// double
0x000000011ed91aa8: vmovsd (%rsp),%xmm0
0x000000011ed91aad: add $0x10,%rsp
0x000000011ed91ab1: vmovsd %xmm0,(%rcx,%rbx,1)
0x000000011ed91ab6: test %edx,%edx
0x000000011ed91ab8: je 0x000000011ed91ac4
0x000000011ed91abe: lock addl $0x0,-0x40(%rsp)
0x000000011ed91ac4: movzbl 0x3(%r13),%ebx
0x000000011ed91ac9: add $0x3,%r13
0x000000011ed91acd: movabs $0x10cf4c950,%r10
0x000000011ed91ad7: jmpq *(%r10,%rbx,8)
0x000000011ed91adb: nopl 0x0(%rax,%rax,1)
呵呵, 参照一下 getstatic, pustatic 的生成代码的代码, resolve_cache_and_index, load_field_cp_cache_entry 都是相同的
resolve_cache_and_index 的主要的作用是将解析 constantsPoolCache 中给定的字段的相关信息(所属类型, 字段索引, 字段偏移, 相关标记信息, 常量池信息)
load_field_cp_cache_entry 的主要作用是 加载字段对应的对象, 加载字段偏移
我们这里着重关注 putstatic 的数据处理部分, 也就是吧栈顶的数据 移动到 cx 对应的对象 上面的 bx 偏移处
另外一点就是 到数据处理这里的时候, cx 存放的是字段对应的对象, bx 存放的是字段的偏移, 这两点信息 是我们待会儿的调试的需要注意的关键点
putstatic 基于 lldb 的调试
在 putstatic 的地方打上断点
(lldb) p _active_table._table[9][179]
(address) $4 = 0x0000000105849aff "A\x0f?U\x01H\x8bM??\U0000008b\\???\x18\x81??
(lldb) b 0x0000000105849aff
Breakpoint 5: address = 0x0000000105849aff
(lldb) c
Process 1964 resuming
Process 1964 stopped
* thread #5, stop reason = breakpoint 5.1
frame #0: 0x0000000105849aff
-> 0x105849aff: movzwl 0x1(%r13), %edx
0x105849b04: movq -0x30(%rbp), %rcx
0x105849b08: shll $0x2, %edx
0x105849b0b: movl 0x10(%rcx,%rdx,8), %ebx
Target 0: (java) stopped.
(lldb) re r
General Purpose Registers:
rax = 0x0000000747bb83e0
rbx = 0x00000000000000b3
rcx = 0x0000000747bb7fb0
rdx = 0x0000000000000008
rdi = 0x0000000105000800
rsi = 0x0000000000000008
rbp = 0x0000700001f12690
rsp = 0x0000700001f12640
r8 = 0x0000000000000000
r9 = 0x0000000100340790
r10 = 0x000000010430b270 libjvm.dylib`TemplateInterpreter::_active_table + 18432
r11 = 0x000000010034078c
r12 = 0x0000000000000000
r13 = 0x000000011e46ef4b
r14 = 0x0000700001f126a8
r15 = 0x0000000105000800
rip = 0x0000000105849aff
rflags = 0x0000000000000206
cs = 0x000000000000002b
fs = 0x0000000000000000
gs = 0x0000000000000000
(lldb) x 0x000000011e46ef4b
0x11e46ef4b: b3 03 00 b2 03 00 10 0a b5 04 00 b2 03 00 b4 04 ?..?....?..?..?.
0x11e46ef5b: 00 3c b1 ff 00 2e 32 41 3a 00 00 00 00 16 00 1b .<??..2A:.......
(lldb) x 0x0000700001f12640 -c 0x30
0x700001f12640: e0 83 bb 47 07 00 00 00 48 26 f1 01 00 70 00 00 ?.?G....H&?..p..
0x700001f12650: 48 ef 46 1e 01 00 00 00 a8 26 f1 01 00 70 00 00 H?F.....?&?..p..
0x700001f12660: 88 f0 46 1e 01 00 00 00 00 00 00 00 00 00 00 00 .?F.............
(lldb)
打印当前的字节码相关信息, 可以定位到当前是在执行 petstatic
b3 03 00 b2 03 00 10 0a
// 转换为字节码信息
putstatic #3 // Field staticInstance:Lcom/hx/test06/Test20GetSetField;
getstatic #2 // Field staticInstance:Lcom/hx/test06/Test20GetSetField;
bipush 10
然后 表达式栈 栈底为 0x700001f12648
表达式栈栈顶上面有一个slot, 0x0000000747bb83e0 对应的是 Test20GetSetField.anotherStaticInstance 的地址
然后在我们数据处理之前打上一个断点
(lldb) b 0x105849db8
Breakpoint 6: address = 0x0000000105849db8
(lldb) c
Process 1964 resuming
Process 1964 stopped
* thread #5, stop reason = breakpoint 6.1
frame #0: 0x0000000105849db8
-> 0x105849db8: jne 0x105849dcd
0x105849dbe: movl (%rsp), %eax
0x105849dc1: addq $0x8, %rsp
0x105849dc5: movb %al, (%rcx,%rbx)
Target 0: (java) stopped.
(lldb) re r
General Purpose Registers:
rax = 0x0000000000000008
rbx = 0x0000000000000070
rcx = 0x0000000747bb7fb0
rdx = 0x0000000000000000
rdi = 0x0000000105000800
rsi = 0x0000000000000008
rbp = 0x0000700001f12690
rsp = 0x0000700001f12640
r8 = 0x000000011e46f0f8
r9 = 0x0000000000000070
r10 = 0x0000000000000000
r11 = 0x0000000100340700
r12 = 0x0000000000000000
r13 = 0x000000011e46ef4b
r14 = 0x0000700001f126a8
r15 = 0x0000000105000800
rip = 0x0000000105849db8
rflags = 0x0000000000000202
cs = 0x000000000000002b
fs = 0x0000000000000000
gs = 0x0000000000000000
可以发现此时 cx 是 0x0000000747bb7fb0 正是 Test20GetSetField.class
然后 bx 是 0x0000000000000070 = 112(十进制), 在 Test20GetSetField.class 的 oop 上面 偏移为 112 的数据是 staticInstance
到断点处 ax 存放的是 字段的类型(atos = 0x08)
然后我们来看一下 数据处理
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x0000000105849dcd
-> 0x105849dcd: cmpl $0x1, %eax
0x105849dd0: jne 0x105849de8
0x105849dd6: movl (%rsp), %eax
0x105849dd9: addq $0x8, %rsp
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x0000000105849dd0
-> 0x105849dd0: jne 0x105849de8
0x105849dd6: movl (%rsp), %eax
0x105849dd9: addq $0x8, %rsp
0x105849ddd: andl $0x1, %eax
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x0000000105849de8
-> 0x105849de8: cmpl $0x8, %eax
0x105849deb: jne 0x10584a141
0x105849df1: popq %rax
0x105849df2: leaq (%rcx,%rbx), %rdx
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x0000000105849deb
-> 0x105849deb: jne 0x10584a141
0x105849df1: popq %rax
0x105849df2: leaq (%rcx,%rbx), %rdx
0x105849df6: cmpb $0x0, 0x550(%r15)
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x0000000105849df1
-> 0x105849df1: popq %rax
0x105849df2: leaq (%rcx,%rbx), %rdx
0x105849df6: cmpb $0x0, 0x550(%r15)
0x105849dfe: je 0x105849f7b
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x0000000105849df2
-> 0x105849df2: leaq (%rcx,%rbx), %rdx
0x105849df6: cmpb $0x0, 0x550(%r15)
0x105849dfe: je 0x105849f7b
0x105849e04: movl (%rdx), %ebx
Target 0: (java) stopped.
(lldb) re r
General Purpose Registers:
rax = 0x0000000747bb83e0
rbx = 0x0000000000000070
rcx = 0x0000000747bb7fb0
rdx = 0x0000000000000000
rdi = 0x0000000105000800
rsi = 0x0000000000000008
rbp = 0x0000700001f12690
rsp = 0x0000700001f12648
r8 = 0x000000011e46f0f8
r9 = 0x0000000000000070
r10 = 0x0000000000000000
r11 = 0x0000000100340700
r12 = 0x0000000000000000
r13 = 0x000000011e46ef4b
r14 = 0x0000700001f126a8
r15 = 0x0000000105000800
rip = 0x0000000105849df2
rflags = 0x0000000000000246
cs = 0x000000000000002b
fs = 0x0000000000000000
gs = 0x0000000000000000
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x0000000105849df6
-> 0x105849df6: cmpb $0x0, 0x550(%r15)
0x105849dfe: je 0x105849f7b
0x105849e04: movl (%rdx), %ebx
0x105849e06: pushq %r10
Target 0: (java) stopped.
(lldb) p ((oopDesc*)0x0000000747bb7fb0)->print()
java.lang.Class
{0x0000000747bb7fb0} - klass: 'java/lang/Class'
- ---- fields (total size 15 words):
- private volatile transient strict 'cachedConstructor' 'Ljava/lang/reflect/Constructor;' @12 NULL (0 0)
- private volatile transient strict 'newInstanceCallerCache' 'Ljava/lang/Class;' @16 NULL (0 e8f77007)
- private transient 'name' 'Ljava/lang/String;' @20 "com.hx.test06.Test20GetSetField"{0x0000000747bb8038} (e8f77007 e8fc0b37)
- private transient 'module' 'Ljava/lang/Module;' @24 a 'java/lang/Module'{0x0000000747e059b8} (e8fc0b37 e8fc0af7)
- private final 'classLoader' 'Ljava/lang/ClassLoader;' @28 a 'jdk/internal/loader/ClassLoaders$AppClassLoader'{0x0000000747e057b8} (e8fc0af7 e8f767c3)
- private transient 'packageName' 'Ljava/lang/String;' @32 "com.hx.test06"{0x0000000747bb3e18} (e8f767c3 0)
- private final strict 'componentType' 'Ljava/lang/Class;' @36 NULL (0 e8f77027)
- private volatile transient strict 'reflectionData' 'Ljava/lang/ref/SoftReference;' @40 a 'java/lang/ref/SoftReference'{0x0000000747bb8138} (e8f77027 0)
- private volatile transient 'genericInfo' 'Lsun/reflect/generics/repository/ClassRepository;' @44 NULL (0 0)
- private volatile transient strict 'enumConstants' '[Ljava/lang/Object;' @48 NULL (0 0)
- private volatile transient strict 'enumConstantDirectory' 'Ljava/util/Map;' @52 NULL (0 0)
- private volatile transient 'annotationData' 'LjavaWarning: hit breakpoint while running function, skipping commands and conditions to prevent recursion.
/langWarning: hit breakpoint while running function, skipping commands and conditions to prevent recursion.
/Class$AnnotationData;' @56 NULL (0 0)
- private volatile transient 'annotationType' 'Lsun/reflect/annotation/AnnotationType;' @60 NULL (0 0)
- transient 'classValueMap' 'Ljava/lang/CWarning: hit breakpoint while running function, skipping commands and conditions to prevent recursion.
lassValue$ClassValueMap;' @64 NULL (0 e8f76f31)Warning: hit breakpoint while running function, skipping commands and conditions to prevent recursion.
- private volatile transient 'classRedefinedCount' 'I' @96 0
- signature: Lcom/hx/test06/Test20GetSetField;
- fake entry for mirror: 'com/hx/test06/Test20GetSetField'
- fake entry for array: NULL
- fake entry for oop_size: 15
- fake entry for static_oop_field_count: 2
- private static 'staticInstance' 'Lcom/hx/tesWarning: hit breakpoint while running function, skipping commands and conditions to prevent recursion.
t06/TeWarning: hit breakpoint while running function, skipping commands and conditions to prevent recursion.
st20GetSetField;' @112 a 'com/hx/test06/Test20GetSetField'{0x0000000747bb8390} (e8f77072 e8f7707c)
- private static 'anotherStaticInstance' 'Lcom/hx/test06/Test20GetSetField;' @116 a 'com/hx/test06/Test20GetSetField'{0x0000000747bb83e0} (e8f7707c 1)
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x0000000105849dfe
-> 0x105849dfe: je 0x105849f7b
0x105849e04: movl (%rdx), %ebx
0x105849e06: pushq %r10
0x105849e08: cmpq -0x153381f(%rip), %r12 ; Universe::_narrow_ptrs_base
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x0000000105849f7b
-> 0x105849f7b: movq %rax, %rbx
0x105849f7e: pushq %r10
0x105849f80: cmpq -0x1533997(%rip), %r12 ; Universe::_narrow_ptrs_base
0x105849f87: je 0x10584a004
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x0000000105849f7e
-> 0x105849f7e: pushq %r10
0x105849f80: cmpq -0x1533997(%rip), %r12 ; Universe::_narrow_ptrs_base
0x105849f87: je 0x10584a004
0x105849f8d: movq %rsp, -0x28(%rsp)
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x0000000105849f80
-> 0x105849f80: cmpq -0x1533997(%rip), %r12 ; Universe::_narrow_ptrs_base
0x105849f87: je 0x10584a004
0x105849f8d: movq %rsp, -0x28(%rsp)
0x105849f92: subq $0x80, %rsp
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x0000000105849f87
-> 0x105849f87: je 0x10584a004
0x105849f8d: movq %rsp, -0x28(%rsp)
0x105849f92: subq $0x80, %rsp
0x105849f99: movq %rax, 0x78(%rsp)
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x000000010584a004
-> 0x10584a004: popq %r10
0x10584a006: shrq $0x3, %rax
0x10584a00a: movl %eax, (%rdx)
0x10584a00c: movq %rdx, %r8
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x000000010584a006
-> 0x10584a006: shrq $0x3, %rax
0x10584a00a: movl %eax, (%rdx)
0x10584a00c: movq %rdx, %r8
0x10584a00f: xorq %rbx, %r8
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x000000010584a00a
-> 0x10584a00a: movl %eax, (%rdx)
0x10584a00c: movq %rdx, %r8
0x10584a00f: xorq %rbx, %r8
0x10584a012: shrq $0x14, %r8
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x000000010584a00c
-> 0x10584a00c: movq %rdx, %r8
0x10584a00f: xorq %rbx, %r8
0x10584a012: shrq $0x14, %r8
0x10584a016: je 0x10584a13c
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x000000010584a00f
-> 0x10584a00f: xorq %rbx, %r8
0x10584a012: shrq $0x14, %r8
0x10584a016: je 0x10584a13c
0x10584a01c: cmpq $0x0, %rbx
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x000000010584a012
-> 0x10584a012: shrq $0x14, %r8
0x10584a016: je 0x10584a13c
0x10584a01c: cmpq $0x0, %rbx
0x10584a020: je 0x10584a13c
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x000000010584a016
-> 0x10584a016: je 0x10584a13c
0x10584a01c: cmpq $0x0, %rbx
0x10584a020: je 0x10584a13c
0x10584a026: movq %rdx, %r8
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x000000010584a13c
-> 0x10584a13c: jmp 0x10584a254
0x10584a141: cmpl $0x4, %eax
0x10584a144: jne 0x10584a159
0x10584a14a: movl (%rsp), %eax
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x000000010584a254
-> 0x10584a254: testl %edx, %edx
0x10584a256: je 0x10584a262
0x10584a25c: lock
0x10584a25d: addl $0x0, -0x40(%rsp)
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x000000010584a256
-> 0x10584a256: je 0x10584a262
0x10584a25c: lock
0x10584a25d: addl $0x0, -0x40(%rsp)
0x10584a262: movzbl 0x3(%r13), %ebx
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x000000010584a25c
-> 0x10584a25c: lock
0x10584a25d: addl $0x0, -0x40(%rsp)
0x10584a262: movzbl 0x3(%r13), %ebx
0x10584a267: addq $0x3, %r13
Target 0: (java) stopped.
(lldb) stepi
Process 1964 stopped
* thread #5, stop reason = instruction step into
frame #0: 0x000000010584a262
-> 0x10584a262: movzbl 0x3(%r13), %ebx
0x10584a267: addq $0x3, %r13
0x10584a26b: movabsq $0x10430b270, %r10 ; imm = 0x10430B270
0x10584a275: jmpq *(%r10,%rbx,8)
Target 0: (java) stopped.
(lldb) p ((oopDesc*)0x0000000747bb7fb0)->print()
java.lang.Class
{0x0000000747bb7fb0} - klass: 'java/lang/Class'
- ---- fields (total size 15 words):
- private volatile transient strict 'cachedConstructor' 'Ljava/lang/reflect/Constructor;' @12 NULL (0 0)
- private volatile transient strict 'newInstanceCallerCache' 'Ljava/lang/Class;' @16 NULL (0 e8f77007)
- private transient 'name' 'Ljava/lang/String;' @20 "com.hx.test06.Test20GetSetField"{0x0000000747bb8038} (e8f77007 e8fc0b37)
- private transient 'module' 'Ljava/lang/Module;' @24 a 'java/lang/Module'{0x0000000747e059b8} (e8fc0b37 e8fc0af7)
- private final 'classLoader' 'Ljava/lang/ClassLoader;' @28 a 'jdk/internal/loader/ClassLoaders$AppClassLoader'{0x0000000747e057b8} (e8fc0af7 e8f767c3)
- private transient 'packageName' 'Ljava/lang/String;' @32 "com.hx.test06"{0x0000000747bb3e18} (e8f767c3 0)
- private final strict 'componentType' 'Ljava/lang/Class;' @36 NULL (0 e8f77027)
- private volatile transient strict 'reflectionData' 'Ljava/lang/ref/SoftReference;' @40 a 'java/lang/ref/SoftReference'{0x0000000747bb8138} (e8f77027 0)
- private volatile transient 'genericInfo' 'Lsun/reflect/generics/repository/ClassRepository;' @44 NULL (0 0)
- private volatile transient strict 'enumConstants' '[Ljava/lang/Object;' @48 NULL (0 0)
- private volatile transient strict 'enumConstantDirectory' 'Ljava/util/Map;' @52 NULL (0 0)
- private volatile transient 'annotationData' 'Ljava/lang/Class$AnnotationData;' @56 NULL (0 0)
- private volatile transient 'annotationType' 'Lsun/reflect/annotation/AnnotationType;' @60 NULL (0 0)
- transient 'classValueMap' 'Ljava/lang/ClassValue$ClassValueMap;' @64 NULL (0 e8f76f31)
- private volatile transient 'classRedefinedCount' 'I' @96 0
- signature: Lcom/hx/test06/Test20GetSetField;
- fake entry for mirror: 'com/hx/test06/Test20GetSetField'
- fake entry for array: NULL
- fake entry for oop_size: 15
- fake entry for static_oop_field_count: 2
- private static 'staticInstance' 'Lcom/hx/test06/Test20GetSetField;' @112 a 'com/hx/test06/Test20GetSetField'{0x0000000747bb83e0} (e8f7707c e8f7707c)
- private static 'anotherStaticInstance' 'Lcom/hx/test06/Test20GetSetField;' @116 a 'com/hx/test06/Test20GetSetField'{0x0000000747bb83e0} (e8f7707c 1)
(lldb)
呵呵 这里的运行时的代码 和 PrintInterpreter 打出来了的似乎是又有一些不同, 不过 实现的效果都是一致 的
0x10584a00a 的地方吧 Test20GetSetField.anotherStaticInstance 引用的对象的地址, 放到了 Test20GetSetField.staticInstance 引用上面, 这下 Test20GetSetField.anotherStaticInstance 和 Test20GetSetField.staticInstance 引用的是同一个对象了
getfield & putfield
void TemplateTable::getfield(int byte_no) {
getfield_or_static(byte_no, false);
}
void TemplateTable::putfield(int byte_no) {
putfield_or_static(byte_no, false);
}
呵呵 同上面使用的同一套代码, 只是存在 细微的不同, 这里就不多 赘述了
resolve_cache_and_index
我们最后 来看一下 解析 constantsPoolCache 中给定的字段的相关信息(所属类型, 字段索引, 字段偏移, 相关标记信息, 常量池信息)
main 线程的第一个 getstatic 如下
遍历 Test20GetSetField 的所有的字段查询字段 anotherStaticInstance
解析 constantsPoolCache 中给定的字段的相关信息(所属类型, 字段索引, 字段偏移, 相关标记信息, 常量池信息)
完
参考
[讨论] 有关实例化的内存分布