문제

Java 최종 방법이 자동으로 인쇄됩니까?

많은 책은 예라고 말합니다. 많은 책들이 아니오라고 말합니다 !!!

도움이 되었습니까?

해결책

흥미로운 질문으로, 더 자세히 살펴 보았습니다. 내가 찾은 흥미로운 말 2-

  • 1 논평 자동 인라인이 버그입니다.

많은 팁의 의미와는 달리, 최종으로 선언 된 방법은 컴파일러가 안전하게 인쇄 할 수 없습니다. 왜냐하면 방법은 런타임에 비정형 선언을 가질 수 있기 때문입니다.

이유를 보려면 컴파일러가 클래스 A 및 서브 클래스 B 및 서브 스 클래스 C를보고 A에서 최종 메소드를보고 C에 인간을 인쇄한다고 가정 해 봅시다. A는 최종적이지 않고 B에서 재정의하지 않습니다. C는 잘못된 인쇄 된 버전을 사용합니다. 티

그리고, 조금 더 권위적으로, a 태양 백서, 그 방법을 작성하는 방법은 가상으로 남을 수 있습니다.

Java Hotspot VM은 대부분의 가상 메소드 호출을 자동으로 인라인 할 수 있으므로이 성능 페널티는 극적으로 감소하고 많은 경우에는 완전히 제거되었습니다.

여기 더 있습니다 직접 참조 메커니즘에.

다른 팁

방법의 인라인은 JAVAC가 아닌 JIT 컴파일러에 의해 수행됩니다.

현대식 JIT 컴파일러 (핫스팟 포함)는 종종 필요한 경우 최적화를 적절하게 "취소"하는 비 결합 방법조차도 인라인 할 수 있습니다. 그들은 기본적으로 무서운 영리합니다.

요컨대 : 그것은 전적으로 VM에 따라 다릅니다. 내 생각에, 당신은 당신의 방법을 성능보다는 가장 깨끗한 코드를 생성하는 것을 기반으로하는 방법을 최종적으로 만들어야합니다. 나는 개인적으로 "상속을위한 디자인 또는 금지"의 팬이지만 다른 토론입니다 :)

"편집 중에 그들이 끊어지는 것"이라는 뜻이라면, 그렇지 않습니다.

그러나 정적 최종 필드는 때때로 컴파일러 (예 : 프리미티브 및 문자열)에 의해 인쇄 될 수 있습니다.

final 컴파일러 나 VM에 무언가를 인라인으로 말하는 것보다 시맨틱을 디자인에 추가하는 것입니다. 현대 VMS는 최종 방법만으로 훨씬 더 많은 인라인이므로 사용해야 할 좋은 이유가 아닙니다. final 또는 런타임 최적화에 대해 너무 많이 예측하십시오.

나는 그것이 당신이 실행중인 JVM의 구현에 달려 있다고 생각합니다. 확실히, 메소드를 최종적으로 만들면 컴파일러가 그러한 구현 조정을 할 수있는 옵션을 사용할 수 있습니다. 그러나 다른 요인에 의존 할 수 있는지 여부는 다른 요인에 의존 할 수 있습니다.

인라인의 여부에 대한 핫스팟의 결정은 엄청나게 복잡하며, 수많은 고려 사항에 의존하지만, 그 방법이 "최종"으로 표시되어 있는지 여부는 생각하지 않습니다. 그 이유는 해당 방법의 여러 구현이 VM에로드되었는지 여부를 이미 알고 있기 때문에 그러한 구현이 허용되는지 여부를 아는 것도 관련이 없기 때문입니다.

어쨌든, 그것은 매우 작고 간단한 방법 일 뿐이며, 심지어 그 모든 것도 아닙니다.

Jon이 말했듯이, Bytecode 생성 레벨이 아닌 JIT 컴파일러는 인라인이 수행됩니다 (필요할 때). 또한 때때로 인라인이 CPU L1 캐시에 동일한 코드가 여러 번 존재하는 상황을 생성하여 다른 코드의 공간을 제거 할 수 있기 때문에 성능 저하가 발생할 수 있습니다. L1 캐시 미스는 캐시 된 기능으로의 점프 이상의 성능에 영향을 줄 수 있습니다.

상수 (일명 최종 정적 VAR)가 대신에 상환됩니다.

확인하려면 이것을 확인하십시오

public class InlineTest {
    final static int add(int x, int y) {
        return x + y;
    } 
}


public class Main {

        static final int DIVISOR = 7;

        static void main(String[] args){
            final int a = new Integer(args[0]);
            final int b = new Integer(args[1]);

            if (InlineTest.add(a, b) % DIVISOR == 0)
                System.exit(InlineTest.add(a, b));

            System.out.print("The sum is " + InlineTest.add(a, b));

        }
}

이것은 다음과 같이 번역됩니다.

 0 new #2 <java/lang/Integer>
 3 dup
 4 aload_0
 5 iconst_0
 6 aaload
 7 invokespecial #3 <java/lang/Integer/<init>(Ljava/lang/String;)V>
10 invokevirtual #4 <java/lang/Integer/intValue()I>
13 istore_1
14 new #2 <java/lang/Integer>
17 dup
18 aload_0
19 iconst_1
20 aaload
21 invokespecial #3 <java/lang/Integer/<init>(Ljava/lang/String;)V>
24 invokevirtual #4 <java/lang/Integer/intValue()I>
27 istore_2
28 iload_1
29 iload_2
30 invokestatic #5 <com/gamasoft/InlineTest/add(II)I>
33 bipush 7
35 irem
36 ifne 47 (+11)
39 iload_1
40 iload_2
41 invokestatic #5 <com/gamasoft/InlineTest/add(II)I>
44 invokestatic #7 <java/lang/System/exit(I)V>
47 getstatic #8 <java/lang/System/out Ljava/io/PrintStream;>
50 new #9 <java/lang/StringBuilder>
53 dup
54 invokespecial #10 <java/lang/StringBuilder/<init>()V>
57 ldc #11 <The sum is >
59 invokevirtual #12 <java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;>
62 iload_1
63 iload_2
64 invokestatic #5 <com/gamasoft/InlineTest/add(II)I>
67 invokevirtual #13 <java/lang/StringBuilder/append(I)Ljava/lang/StringBuilder;>
70 invokevirtual #14 <java/lang/StringBuilder/toString()Ljava/lang/String;>
73 invokevirtual #15 <java/io/PrintStream/print(Ljava/lang/String;)V>
76 return

정적 함수 inlineTest.add가 여러 번 호출되었음을 알 수 있습니다. invokestatic

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top