问题描述
这是递归吗?
public class Test {
Test test = new Test();
public static void main(String[] args) {
new Test();
}
}
?
public class Test {
{ Test test = new Test(); }
public static void main(String[] args) {
new Test();
}
}
推荐答案
我的意见是它是递归。我不能找到好的来源或反对它,虽然。所以我试图比较一个已知的递归函数的汇编代码和生成的汇编代码的java代码在OP。
My opinion is that it is recursion. I am not able to find good sources for or against it though. So I have tried to compare the assembly code of a known recursive function with generated assembly code of java code in OP. The two assembly codes are fairly similar, in the question it happens for the method (Constructor) that calls itself.
我的测试代码:
public class Test3 {
void printMe() {
printMe();
}
public static void main(String[] args) {
Test3 test = new Test3();
test.printMe();
}
}
打印装配:
java -XX:+ UnlockDiagnosticVMOptions -XX:+ PrintAssembly -server -cp。 Test3
相关的汇编代码序列,显示函数调用自身:
Relevant assembly code sequence, showing that the function calls itself:
Decoding compiled method 0x00007f2e2910ac90:
Code:
[Entry Point]
[Constants]
# {method} {0x00007f2e27121230} 'printMe' '()V' in 'com/vs/soutils/Test3'
# [sp+0x40] (sp of caller)
0x00007f2e2910ae00: mov 0x8(%rsi),%r10d
0x00007f2e2910ae04: shl $0x3,%r10
0x00007f2e2910ae08: cmp %rax,%r10
0x00007f2e2910ae0b: jne 0x00007f2e29045b60 ; {runtime_call}
0x00007f2e2910ae11: nopw 0x0(%rax,%rax,1)
0x00007f2e2910ae1c: xchg %ax,%ax
[Verified Entry Point]
0x00007f2e2910ae20: mov %eax,-0x14000(%rsp)
0x00007f2e2910ae27: push %rbp
0x00007f2e2910ae28: sub $0x30,%rsp
0x00007f2e2910ae2c: mov $0x7f2e271213f8,%rdi ; {metadata(method data for {method} {0x00007f2e27121230} 'printMe' '()V' in 'com/vs/soutils/Test3')}
0x00007f2e2910ae36: mov 0x64(%rdi),%ebx
0x00007f2e2910ae39: add $0x8,%ebx
0x00007f2e2910ae3c: mov %ebx,0x64(%rdi)
0x00007f2e2910ae3f: mov $0x7f2e27121230,%rdi ; {metadata({method} {0x00007f2e27121230} 'printMe' '()V' in 'com/vs/soutils/Test3')}
0x00007f2e2910ae49: and $0x1ff8,%ebx
0x00007f2e2910ae4f: cmp $0x0,%ebx
0x00007f2e2910ae52: je 0x00007f2e2910aec0 ;*aload_0
; - com.vs.soutils.Test3::printMe@0 (line 6)
0x00007f2e2910ae58: mov %rsi,%rdi
0x00007f2e2910ae5b: mov $0x7f2e271213f8,%rbx ; {metadata(method data for {method} {0x00007f2e27121230} 'printMe' '()V' in 'com/vs/soutils/Test3')}
0x00007f2e2910ae65: addq $0x1,0xa0(%rbx)
0x00007f2e2910ae6d: mov $0x7f2e271213f8,%rdi ; {metadata(method data for {method} {0x00007f2e27121230} 'printMe' '()V' in 'com/vs/soutils/Test3')}
0x00007f2e2910ae77: mov 0x64(%rdi),%ebx
0x00007f2e2910ae7a: add $0x8,%ebx
0x00007f2e2910ae7d: mov %ebx,0x64(%rdi)
0x00007f2e2910ae80: mov $0x7f2e27121230,%rdi ; {metadata({method} {0x00007f2e27121230} 'printMe' '()V' in 'com/vs/soutils/Test3')}
0x00007f2e2910ae8a: and $0x7ffff8,%ebx
0x00007f2e2910ae90: cmp $0x0,%ebx
0x00007f2e2910ae93: je 0x00007f2e2910aed4
0x00007f2e2910ae99: mov %rsi,%rdi
0x00007f2e2910ae9c: mov $0x7f2e271213f8,%rbx ; {metadata(method data for {method} {0x00007f2e27121230} 'printMe' '()V' in 'com/vs/soutils/Test3')}
0x00007f2e2910aea6: addq $0x1,0xa0(%rbx)
0x00007f2e2910aeae: nop
0x00007f2e2910aeaf: callq 0x00007f2e29045d60 ; OopMap{off=180}
;*invokevirtual printMe
; - com.vs.soutils.Test3::printMe@1 (line 6)
; - com.vs.soutils.Test3::printMe@1 (line 6)
; {optimized virtual_call}
0x00007f2e2910aeb4: add $0x30,%rsp
0x00007f2e2910aeb8: pop %rbp
0x00007f2e2910aeb9: test %eax,0x16461241(%rip) # 0x00007f2e3f56c100
; {poll_return}
0x00007f2e2910aebf: retq
0x00007f2e2910aec0: mov %rdi,0x8(%rsp)
0x00007f2e2910aec5: movq $0xffffffffffffffff,(%rsp)
0x00007f2e2910aecd: callq 0x00007f2e290fdde0 ; OopMap{rsi=Oop off=210}
;*synchronization entry
; - com.vs.soutils.Test3::printMe@-1 (line 6)
; {runtime_call}
0x00007f2e2910aed2: jmp 0x00007f2e2910ae58
0x00007f2e2910aed4: mov %rdi,0x8(%rsp)
0x00007f2e2910aed9: movq $0xffffffffffffffff,(%rsp)
0x00007f2e2910aee1: callq 0x00007f2e290fdde0 ; OopMap{rsi=Oop off=230}
;*synchronization entry
; - com.vs.soutils.Test3::printMe@-1 (line 6)
; - com.vs.soutils.Test3::printMe@1 (line 6)
; {runtime_call}
0x00007f2e2910aee6: jmp 0x00007f2e2910ae99
0x00007f2e2910aee8: nop
0x00007f2e2910aee9: nop
0x00007f2e2910aeea: mov 0x288(%r15),%rax
0x00007f2e2910aef1: mov $0x0,%r10
0x00007f2e2910aefb: mov %r10,0x288(%r15)
0x00007f2e2910af02: mov $0x0,%r10
0x00007f2e2910af0c: mov %r10,0x290(%r15)
0x00007f2e2910af13: add $0x30,%rsp
0x00007f2e2910af17: pop %rbp
0x00007f2e2910af18: jmpq 0x00007f2e2906be20 ; {runtime_call}
现在将其与原始代码的汇编代码进行比较:
Now compare it with the assembly code for original code:
Decoding compiled method 0x00007fea24ef0dd0:
Code:
[Entry Point]
[Constants]
# {method} {0x00007fea229431b0} '<init>' '()V' in 'com/vs/soutils/Test'
# [sp+0x80] (sp of caller)
0x00007fea24ef0f60: mov 0x8(%rsi),%r10d
0x00007fea24ef0f64: shl $0x3,%r10
0x00007fea24ef0f68: cmp %rax,%r10
0x00007fea24ef0f6b: jne 0x00007fea24e29b60 ; {runtime_call}
0x00007fea24ef0f71: nopw 0x0(%rax,%rax,1)
0x00007fea24ef0f7c: xchg %ax,%ax
[Verified Entry Point]
0x00007fea24ef0f80: mov %eax,-0x14000(%rsp)
0x00007fea24ef0f87: push %rbp
0x00007fea24ef0f88: sub $0x70,%rsp
0x00007fea24ef0f8c: mov $0x7fea22943350,%rdx ; {metadata(method data for {method} {0x00007fea229431b0} '<init>' '()V' in 'com/vs/soutils/Test')}
0x00007fea24ef0f96: mov 0x64(%rdx),%edi
0x00007fea24ef0f99: add $0x8,%edi
0x00007fea24ef0f9c: mov %edi,0x64(%rdx)
0x00007fea24ef0f9f: mov $0x7fea229431b0,%rdx ; {metadata({method} {0x00007fea229431b0} '<init>' '()V' in 'com/vs/soutils/Test')}
0x00007fea24ef0fa9: and $0x1ff8,%edi
0x00007fea24ef0faf: cmp $0x0,%edi
0x00007fea24ef0fb2: je 0x00007fea24ef1172 ;*aload_0
; - com.vs.soutils.Test::<init>@0 (line 3)
0x00007fea24ef0fb8: mov %rsi,%rdx
0x00007fea24ef0fbb: mov $0x7fea22943350,%rdi ; {metadata(method data for {method} {0x00007fea229431b0} '<init>' '()V' in 'com/vs/soutils/Test')}
0x00007fea24ef0fc5: addq $0x1,0x90(%rdi)
0x00007fea24ef0fcd: mov $0x7fea226a1f10,%rdx ; {metadata(method data for {method} {0x00007fea22543488} '<init>' '()V' in 'java/lang/Object')}
0x00007fea24ef0fd7: mov 0x64(%rdx),%edi
0x00007fea24ef0fda: add $0x8,%edi
0x00007fea24ef0fdd: mov %edi,0x64(%rdx)
0x00007fea24ef0fe0: mov $0x7fea22543488,%rdx ; {metadata({method} {0x00007fea22543488} '<init>' '()V' in 'java/lang/Object')}
0x00007fea24ef0fea: and $0x7ffff8,%edi
0x00007fea24ef0ff0: cmp $0x0,%edi
0x00007fea24ef0ff3: je 0x00007fea24ef1189
0x00007fea24ef0ff9: mov $0x7c0060028,%rdx ; {metadata('com/vs/soutils/Test')}
0x00007fea24ef1003: mov %rsi,0x58(%rsp)
0x00007fea24ef1008: mov 0x60(%r15),%rax
0x00007fea24ef100c: lea 0x10(%rax),%rdi
0x00007fea24ef1010: cmp 0x70(%r15),%rdi
0x00007fea24ef1014: ja 0x00007fea24ef11a0
0x00007fea24ef101a: mov %rdi,0x60(%r15)
0x00007fea24ef101e: mov 0xa8(%rdx),%rcx
0x00007fea24ef1025: mov %rcx,(%rax)
0x00007fea24ef1028: mov %rdx,%rcx
0x00007fea24ef102b: shr $0x3,%rcx
0x00007fea24ef102f: mov %ecx,0x8(%rax)
0x00007fea24ef1032: xor %rcx,%rcx
0x00007fea24ef1035: mov %ecx,0xc(%rax)
0x00007fea24ef1038: xor %rcx,%rcx ;*new ; - com.vs.soutils.Test::<init>@5 (line 5)
0x00007fea24ef103b: mov %rax,%rdx
0x00007fea24ef103e: mov $0x7fea22943350,%rsi ; {metadata(method data for {method} {0x00007fea229431b0} '<init>' '()V' in 'com/vs/soutils/Test')}
0x00007fea24ef1048: addq $0x1,0xa0(%rsi)
0x00007fea24ef1050: mov $0x7fea22943350,%rdx ; {metadata(method data for {method} {0x00007fea229431b0} '<init>' '()V' in 'com/vs/soutils/Test')}
0x00007fea24ef105a: mov 0x64(%rdx),%esi
0x00007fea24ef105d: add $0x8,%esi
0x00007fea24ef1060: mov %esi,0x64(%rdx)
0x00007fea24ef1063: mov $0x7fea229431b0,%rdx ; {metadata({method} {0x00007fea229431b0} '<init>' '()V' in 'com/vs/soutils/Test')}
0x00007fea24ef106d: and $0x7ffff8,%esi
0x00007fea24ef1073: cmp $0x0,%esi
0x00007fea24ef1076: je 0x00007fea24ef11ad
0x00007fea24ef107c: mov %rax,%rdx
0x00007fea24ef107f: mov $0x7fea22943350,%rsi ; {metadata(method data for {method} {0x00007fea229431b0} '<init>' '()V' in 'com/vs/soutils/Test')}
0x00007fea24ef1089: addq $0x1,0x90(%rsi)
0x00007fea24ef1091: mov $0x7fea226a1f10,%rdx ; {metadata(method data for {method} {0x00007fea22543488} '<init>' '()V' in 'java/lang/Object')}
0x00007fea24ef109b: mov 0x64(%rdx),%esi
0x00007fea24ef109e: add $0x8,%esi
0x00007fea24ef10a1: mov %esi,0x64(%rdx)
0x00007fea24ef10a4: mov $0x7fea22543488,%rdx ; {metadata({method} {0x00007fea22543488} '<init>' '()V' in 'java/lang/Object')}
0x00007fea24ef10ae: and $0x7ffff8,%esi
0x00007fea24ef10b4: cmp $0x0,%esi
0x00007fea24ef10b7: je 0x00007fea24ef11c4
0x00007fea24ef10bd: mov $0x7c0060028,%rdx ; {metadata('com/vs/soutils/Test')}
0x00007fea24ef10c7: mov %rax,0x50(%rsp)
0x00007fea24ef10cc: mov 0x60(%r15),%rax
0x00007fea24ef10d0: lea 0x10(%rax),%rdi
0x00007fea24ef10d4: cmp 0x70(%r15),%rdi
0x00007fea24ef10d8: ja 0x00007fea24ef11db
0x00007fea24ef10de: mov %rdi,0x60(%r15)
0x00007fea24ef10e2: mov 0xa8(%rdx),%rcx
0x00007fea24ef10e9: mov %rcx,(%rax)
0x00007fea24ef10ec: mov %rdx,%rcx
0x00007fea24ef10ef: shr $0x3,%rcx
0x00007fea24ef10f3: mov %ecx,0x8(%rax)
0x00007fea24ef10f6: xor %rcx,%rcx
0x00007fea24ef10f9: mov %ecx,0xc(%rax)
0x00007fea24ef10fc: xor %rcx,%rcx ;*new ; - com.vs.soutils.Test::<init>@5 (line 5)
; - com.vs.soutils.Test::<init>@9 (line 5)
0x00007fea24ef10ff: mov %rax,%rsi
0x00007fea24ef1102: mov $0x7fea22943350,%rdi ; {metadata(method data for {method} {0x00007fea229431b0} '<init>' '()V' in 'com/vs/soutils/Test')}
0x00007fea24ef110c: addq $0x1,0xa0(%rdi)
0x00007fea24ef1114: mov %rax,%rsi ;*invokespecial <init>
; - com.vs.soutils.Test::<init>@9 (line 5)
; - com.vs.soutils.Test::<init>@9 (line 5)
0x00007fea24ef1117: mov %rax,0x48(%rsp)
0x00007fea24ef111c: nop
0x00007fea24ef111d: nop
0x00007fea24ef111e: nop
0x00007fea24ef111f: callq 0x00007fea24e29d60 ; OopMap{[72]=Oop [80]=Oop [88]=Oop off=452}
;*invokespecial <init>
; - com.vs.soutils.Test::<init>@9 (line 5)
; - com.vs.soutils.Test::<init>@9 (line 5)
; {optimized virtual_call}
0x00007fea24ef1124: mov 0x48(%rsp),%rsi
0x00007fea24ef1129: mov 0x50(%rsp),%rax
0x00007fea24ef112e: mov %rsi,%r10
0x00007fea24ef1131: shr $0x3,%r10
0x00007fea24ef1135: mov %r10d,0xc(%rax)
0x00007fea24ef1139: mov %rax,%rsi
0x00007fea24ef113c: shr $0x9,%rsi
0x00007fea24ef1140: mov $0x7fea20c23000,%rdi
0x00007fea24ef114a: movb $0x0,(%rsi,%rdi,1) ;*putfield test
; - com.vs.soutils.Test::<init>@12 (line 5)
; - com.vs.soutils.Test::<init>@9 (line 5)
0x00007fea24ef114e: mov 0x58(%rsp),%rsi
0x00007fea24ef1153: mov %rax,%r10
0x00007fea24ef1156: shr $0x3,%r10
0x00007fea24ef115a: mov %r10d,0xc(%rsi)
0x00007fea24ef115e: shr $0x9,%rsi
0x00007fea24ef1162: movb $0x0,(%rsi,%rdi,1) ;*putfield test
; - com.vs.soutils.Test::<init>@12 (line 5)
0x00007fea24ef1166: add $0x70,%rsp
0x00007fea24ef116a: pop %rbp
0x00007fea24ef116b: test %eax,0x15e21f8f(%rip) # 0x00007fea3ad13100
; {poll_return}
0x00007fea24ef1171: retq
0x00007fea24ef1172: mov %rdx,0x8(%rsp)
0x00007fea24ef1177: movq $0xffffffffffffffff,(%rsp)
0x00007fea24ef117f: callq 0x00007fea24ee1d20 ; OopMap{rsi=Oop off=548}
;*synchronization entry
; - com.vs.soutils.Test::<init>@-1 (line 3)
; {runtime_call}
0x00007fea24ef1184: jmpq 0x00007fea24ef0fb8
0x00007fea24ef1189: mov %rdx,0x8(%rsp)
0x00007fea24ef118e: movq $0xffffffffffffffff,(%rsp)
0x00007fea24ef1196: callq 0x00007fea24ee1d20 ; OopMap{rsi=Oop off=571}
;*synchronization entry
; - java.lang.Object::<init>@-1 (line 37)
; - com.vs.soutils.Test::<init>@1 (line 3)
; {runtime_call}
0x00007fea24ef119b: jmpq 0x00007fea24ef0ff9
0x00007fea24ef11a0: mov %rdx,%rdx
0x00007fea24ef11a3: callq 0x00007fea24edda60 ; OopMap{[88]=Oop off=584}
;*new ; - com.vs.soutils.Test::<init>@5 (line 5)
; {runtime_call}
0x00007fea24ef11a8: jmpq 0x00007fea24ef103b
0x00007fea24ef11ad: mov %rdx,0x8(%rsp)
0x00007fea24ef11b2: movq $0xffffffffffffffff,(%rsp)
0x00007fea24ef11ba: callq 0x00007fea24ee1d20 ; OopMap{[88]=Oop rax=Oop off=607}
;*synchronization entry
; - com.vs.soutils.Test::<init>@-1 (line 3)
; - com.vs.soutils.Test::<init>@9 (line 5)
; {runtime_call}
0x00007fea24ef11bf: jmpq 0x00007fea24ef107c
0x00007fea24ef11c4: mov %rdx,0x8(%rsp)
0x00007fea24ef11c9: movq $0xffffffffffffffff,(%rsp)
0x00007fea24ef11d1: callq 0x00007fea24ee1d20 ; OopMap{[88]=Oop rax=Oop off=630}
;*synchronization entry
; - java.lang.Object::<init>@-1 (line 37)
; - com.vs.soutils.Test::<init>@1 (line 3)
; - com.vs.soutils.Test::<init>@9 (line 5)
; {runtime_call}
0x00007fea24ef11d6: jmpq 0x00007fea24ef10bd
0x00007fea24ef11db: mov %rdx,%rdx
0x00007fea24ef11de: callq 0x00007fea24edda60 ; OopMap{[88]=Oop [80]=Oop off=643}
;*new ; - com.vs.soutils.Test::<init>@5 (line 5)
; - com.vs.soutils.Test::<init>@9 (line 5)
; {runtime_call}
0x00007fea24ef11e3: jmpq 0x00007fea24ef10ff
0x00007fea24ef11e8: nop
0x00007fea24ef11e9: nop
0x00007fea24ef11ea: mov 0x288(%r15),%rax
0x00007fea24ef11f1: mov $0x0,%r10
0x00007fea24ef11fb: mov %r10,0x288(%r15)
0x00007fea24ef1202: mov $0x0,%r10
0x00007fea24ef120c: mov %r10,0x290(%r15)
0x00007fea24ef1213: add $0x70,%rsp
0x00007fea24ef1217: pop %rbp
0x00007fea24ef1218: jmpq 0x00007fea24edcce0 ; {runtime_call}
0x00007fea24ef121d: hlt
我们看到构造函数被反复调用。这解释了堆栈溢出,并且似乎是递归的。
We see the constructor being invoked over and over again. That explains the stack overflow, and appears to be recursive.
这篇关于实例化类中的Test Test类中的成员Test a recursion?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!