2014-02-22 7 views
4

javac 또는 JIT는 불필요한 오토 박싱을 최적화합니까? 이 코드 조각이 있다고 가정 해 봅시다.JVM이 불필요한 오토 박싱을 최적화합니까?

for(int i=0; i<100000; i++) { 
    f(i); 
} 

void f(Integer i) { 
    System.out.println(i); 
} 

코드 조각이 어떻게 최적화됩니까? 나는 f가 인라인 될 것 같지만, int의 불필요한 복싱 (수정되지 않고 절대로 null)은 어떨까요? 메소드가 다른 코드 조각에서 호출되지 않는다고 가정 해 봅시다. 메소드 서명이
void f(final Integer i) 인 경우 어떤 차이가 있습니까?

답변

2

JVM은 원하는 최적화를 자유롭게 수행 할 수 있으므로 일부 JVM에서는이를 최적화 할 수 있습니다.

그렇다고 가정하는 것이 좋지 않으며 여러 가지 JVM이있을 수 있습니다.

그냥 이것 좀보세요 때 .. 그 안에 사용하기 때문에 권투의 같은 레벨의 유형을 받아

+0

글쎄, 내 기술 인터뷰 중 하나에 질문이 있는데 그 질문을받은 사람이 오히려 구체적인 대답을 기대하고 있었다. 우리는 HotSpot JVM에 대해 이야기하고있었습니다. 나는 당신의 요점을 이해하고 그것에 동의합니다. – Sebastian

1

을하는 방법을 변경

public class a 
{ 
    public static void main(String[] args) 
    { 
     for (int i = 0; i < 100000; i++) 
      f(i); 
    } 

    public static void f(Integer i) 
    { 
     System.out.println(i); 
    } 
} 

을하고 모양이 어떻게되는지 확인 javac a.java && javap -c a를 호출 한 후, 당신은

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

    public static void main(java.lang.String[]); 
    Code: 
     0: iconst_0  
     1: istore_1  
     2: iload_1  
     3: ldc   #2     // int 100000 
     5: if_icmpge  21 
     8: iload_1  
     9: invokestatic #3     // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 
     12: invokestatic #4     // Method f:(Ljava/lang/Integer;)V 
     15: iinc   1, 1 
     18: goto   2 
     21: return   

    public static void f(java.lang.Integer); 
    Code: 
     0: getstatic  #5     // Field java/lang/System.out:Ljava/io/PrintStream; 
     3: aload_0  
     4: invokevirtual #6     // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 
     7: return   
} 

거야이 바이트 코드는 Integer.valueOf()이 (main 9:)라고되고 있음, 따라서 더 최적화 탁을 우리에게 보여줍니다 이 경우에는 컴파일 레벨에 배치됩니다. 그러나 @Tim B가 지적한 것처럼 JVM 내부에서 일어나는 일은 예측할 수없는 또 다른 문제입니다. 최악의 시나리오를 가정하는 것이 가장 좋습니다. JVM은이를 최적화하지 않습니다.

+6

'javac'는 거의 최적화를하지 않고 바이트 코드를 읽는 것이 최적화되었을 때 코드가하는 일에 대한 좋은 테스트가 아닙니다. –

4

오픈 JDK 및 핫스팟 JVM 5-8가 (그렇다하더라도 항상 등)를 사용하지 않는 한

그러나, 당신이 물어 때 관점의 감각을 가지고하는 것이 중요하다, 그들을 멀리 최적화하지 않습니다 문제를 해결하거나 대답하십시오. Autoboixing은 숫자를 String으로 변환하는 코드 (JVM이 어쨌든 그것을하는 방식)와 비교하면 사소한 것이고 이것은 콘솔에 쓰는 것과 비교하면 사소한 것입니다. System.out.println()을 꺼내면 99.99 % + 시간을 절약 할 수 있습니다. 여기에서 자동 흥분에 대한 걱정은 잘못된 것에 대한 걱정입니다.

구체적인 경우 PrintStream.println (Object)가 호출되므로 오토 박싱을 최적화 할 수 없습니다. JVM은 일반적으로 라이브러리가하는 일을 이해하지 못하기 때문에 PrintStream.println (int)을 호출하면 동일한 작업을 수행한다는 가정을 할 수 없습니다.

+0

글쎄 메모리 효율성은 어떨까요? 모든 호출에서 오토 박싱이 발생하면 약 99873 (100000-127) 개의 정수 인스턴스가 불필요하게 생성됩니다. 나는 오토 박싱에 대해 걱정할 필요가 없다는데 동의하지 않는다. println (Object)를 호출했기 때문에이 경우가 최적화되지 않는 이유를 알았습니다. – Sebastian

+2

@Sebastian이 맞다. 아무 것도하지 않는다는 말은 아니다. 단지 텍스트로 변환하는 비용이 훨씬 높고 화면에 쓰는 비용이 훨씬 높다. println make를 가져 오는 차이가 Integer를 꺼내는 것과 얼마나 다른지 비교해보십시오. 당신은 그것을 측정 할 필요가 없습니다. 그 차이는 너무 커서 차이를 보게 될 것입니다. –