2014-10-21 50 views
4

假設我有一個聲明元的陣列的方法,但不使用它:未使用的基元數組:javac和JIT編譯器用它做什麼?

public void frobnicate() { 
    int[] pointless = new int[1000]; 
    System.out.println("bored"); 
} 

會發生什麼我pointless陣列?我認爲javac會保留它(雖然我不確定)。如果是這樣,JIT編譯器會做什麼?它會完全擺脫它嗎?它會創建數組而不是對它的引用嗎?

在這裏有黑暗的水域。它不是一樣的未使用

int pointless = 23; 

這可以很容易地刪除。使用數組時,會創建一個對象實例,然後將其清零。 JIT編譯器能否把這一切都解決掉?還是所有的工作仍會完成?順便說一句,這個動機是我正在編寫一個基準,看看不同緩衝區大小的影響。我想刪除不同大小緩衝區的空間分配效果。在內部,緩衝區只是一個byte[];因此刪除內存分配效果的最簡單方法是通過創建一個未使用的數組來啓動該方法,以便在每種情況下分配的總量相同。換句話說,如果我要測試的最大緩衝區大小是4MB,那麼當我使用1MB緩衝區進行測試時,我首先創建一個未使用的byte[3*1024*1024],這樣分配的總量仍然是4MB。 (我準備忽略額外開銷的幾個字節,這應該是微不足道的。)

但是,顯然沒有必要試圖分配未使用的數組,如果它永遠不會超過JIT編譯器...

+0

因此int []是一個對象,它會被創建並被銷燬,int將被放在棧上,int []放在堆上,我會懷疑JIT會跳過它 – 2014-10-21 21:37:08

+0

當你創建一個'Integer.MAX_VALUE ' - 你不用?看看內存使用情況。數組何時被丟棄?也許你應該在你的基準調用之後對陣列做些什麼......等 – TheConstructor 2014-10-21 22:23:07

+1

爲什麼不找你自己? 'javap'就在那裏。 – chrylis 2014-10-21 22:48:20

回答

2

Java microbenchmarks很難。然而,咋一看通過字節碼爲frobincate表明的javac(OpenJDK 7的)不所述的Elid陣列...

Compiled from "Frobincate.java" 
public class Frobincate { 
    public Frobincate(); 
    Code: 
     0: aload_0  
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: return   

    public static void frobincate(); 
    Code: 
     0: sipush  1000 
     3: newarray  int 
     5: astore_0  
     6: getstatic  #2     // Field java/lang/System.out:Ljava/io/PrintStream; 
     9: ldc   #3     // String bored 
     11: invokevirtual #4     // Method java/io/PrintStream.println:(Ljava/lang/String;)V 
     14: return   
} 

挖入組件還示出了對象(數組分配)未由JVM消隱...

[Disassembling for mach='i386:x86-64'] 
[Entry Point] 
[Verified Entry Point] 
[Constants] 
    # {method} 'frobincate' '()V' in 'Foo' 
    #   [sp+0x20] (sp of caller) 
    0x00007fd335060aa0: mov %eax,-0x14000(%rsp) 
    0x00007fd335060aa7: push %rbp 
    0x00007fd335060aa8: sub $0x10,%rsp   ;*synchronization entry 
               ; - Foo::[email protected] (line 4) 
    0x00007fd335060aac: mov 0x60(%r15),%rdi 
    0x00007fd335060ab0: mov %rdi,%r10 
    0x00007fd335060ab3: add $0xfb0,%r10 
    0x00007fd335060aba: cmp 0x70(%r15),%r10 
    0x00007fd335060abe: jae 0x00007fd335060b18 
    0x00007fd335060ac0: mov %r10,0x60(%r15) 
    0x00007fd335060ac4: prefetchnta 0xc0(%r10) 
    0x00007fd335060acc: movq $0x1,(%rdi) 
    0x00007fd335060ad3: prefetchnta 0x100(%r10) 
    0x00007fd335060adb: movl $0xe7780204,0x8(%rdi) ; {oop({type array int})} 
    0x00007fd335060ae2: prefetchnta 0x140(%r10) 
    0x00007fd335060aea: movl $0x3e8,0xc(%rdi) 
    0x00007fd335060af1: prefetchnta 0x180(%r10) 
    0x00007fd335060af9: add $0x10,%rdi 
    0x00007fd335060afd: mov $0x1f4,%ecx 
    0x00007fd335060b02: xor %rax,%rax 
    0x00007fd335060b05: shl $0x3,%rcx 
    0x00007fd335060b09: rex.W rep stos %al,%es:(%rdi) 
    0x00007fd335060b0c: add $0x10,%rsp 
    0x00007fd335060b10: pop %rbp 
    0x00007fd335060b11: test %eax,0xbb954e9(%rip)  # 0x00007fd340bf6000 
               ; {poll_return} 
    0x00007fd335060b17: retq 
    0x00007fd335060b18: mov $0x3e8,%edx 
    0x00007fd335060b1d: mov $0x73bc01020,%rsi ; {oop({type array int})} 
    0x00007fd335060b27: callq 0x00007fd33505f260 ; OopMap{off=140} 
               ;*newarray 
               ; - Foo::[email protected] (line 4) 
               ; {runtime_call} 
    0x00007fd335060b2c: jmp 0x00007fd335060b0c ;*newarray 
               ; - Foo::[email protected] (line 4) 
    0x00007fd335060b2e: mov %rax,%rsi 
    0x00007fd335060b31: add $0x10,%rsp 
    0x00007fd335060b35: pop %rbp 
    0x00007fd335060b36: jmpq 0x00007fd335062160 ; {runtime_call} 
    0x00007fd335060b3b: hlt  
    0x00007fd335060b3c: hlt  
    0x00007fd335060b3d: hlt  
    0x00007fd335060b3e: hlt  
    0x00007fd335060b3f: hlt  
[Exception Handler] 
[Stub Code] 
    0x00007fd335060b40: jmpq 0x00007fd33505f3e0 ; {no_reloc} 
[Deopt Handler Code] 
    0x00007fd335060b45: callq 0x00007fd335060b4a 
    0x00007fd335060b4a: subq $0x5,(%rsp) 
    0x00007fd335060b4f: jmpq 0x00007fd335038f00 ; {runtime_call} 
    0x00007fd335060b54: hlt  
    0x00007fd335060b55: hlt  
    0x00007fd335060b56: hlt  
    0x00007fd335060b57: hlt 

雖然這是一個明顯的優化,它取決於編譯器/ jvm /架構/平臺。因此,爲基準參數化緩衝區可能更安全。另一種選擇是將緩衝區設爲publicstatic成員,或將參考存儲爲publicstatic成員。它增加了編譯器可以有效優化的範圍。

2

我不能回答的主要問題,但我可以提供一個補救措施:

取出內存分配的影響將是通過創建一個未使用的陣列

啓動方法的最簡單方法

只是「使用「陣列。如果您使用JMH,請將其分配給黑洞。如果您使用的是卡尺,請執行result += myArray.hashCode()之類的操作。看看長度的不同,JMH會避免死代碼排除的風險,我絕不會寫一個允許任何死代碼的基準測試。它可能會或可能不會工作,並且可能隨時破壞。