7

내가 javac의 코드 제거 기능에 대한 정보를 찾는 힘든 시간을 보내고 있습니다 :javac의 코드 제거 기능

난 당신이 다음과 같이있는 경우 if -statement이 제거됩니다 읽기 :

static final boolean DEBUG = false; 

if (DEBUG) System.out.println("Hello World!"); // will be removed 

하지만 어떻게 이것에 대해, 예를 들어 :

static final int VALUE = 3; 

if (VALUE > 9) System.out.println("VALUE > 9 ???"); // will this be removed? 

또는 생 S :

static final SomeEnum VALUE = SomeEnum.FOO; 

if (VALUE==SomeEnum.BAR) System.out.println("Bar???"); // will this be removed? 

이 (중단 문제에 아마 유사) 모든 죽은 코드를 찾을 수있는 프로그램을 분석하는 것은 매우/어려운 불가능하기 때문에, 나는 처음과 같은 몇 잘 정의 된 구조 (이 있다는 것을 상상 위의 예) javac은 확실하게 인식하고 제거합니다. 이러한 구조의 포괄적 인 목록이 있습니까?

+1

잘 보셨습니까? 'javap -c'로하면 꽤 명확해질 것입니다 ... –

+2

@JonSkeet 나는이 구조체의리스트를 찾기를 희망하고 있기 때문에 나는 아직하지 않았습니다. 그래서 하나씩 차례로 시도 할 필요가 없습니다. 또한, 아마도 모든 가능성을 생각해 낼 수는 없을 것입니다 ... 그러나 위의 두 가지 예를 들어 보면 물론, 당신이 옳을 것입니다 ... –

+1

기록을 위해 처음 두 개는 제거됩니다. 세 번째 것은 아닙니다. – assylias

답변

7

assylias 보인다 (나를 그냥 모두 함께 넣어 보자) :

Chapter "14.21. Unreachable Statements" of the JLS은 조건부 컴파일을 특별히 허용하기 위해 if 문구의 특수 처리 만 제외하고 일반적으로 코드에서 도달 할 수없는 문이 컴파일 타임 오류로 간주된다는 것을 지정합니다.(! 컴파일러는 이렇게하도록 선택하는 경우)

따라서 코드 제거에 해당 수도 결과를 구성이다

if (compileTimeConstantExpression) { 
    doThis(); // may be removed if compileTimeConstantExpression == false; 
} else { 
    doThat(); // may be removed if compileTimeConstantExpression == true; 
} 

합니다 (else part의 물론, 선택적인)

코드 제거를 허용하는 다른 모든 구조 (예 : while (false) ...)는 허용되지 않으며 조건부 컴파일로 이어지는 대신 컴파일 타임 오류가 발생합니다.

수용 가능한 compileTimeConstantExpression을 구성하는 정의는 chapter "15.28. Constant Expressions" of the JLS에서 찾을 수 있습니다. 자세한 예제와 함께 또 다른 위대한 페이지는 여기에서 찾을 수 있습니다 : Compile Time Constants in Java

참고 : 컴파일러가 if -stament의 "도달"섹션을 제거하는 대한 요구 사항이 없습니다. javac이 작업을 안정적으로 수행하는 것으로 보이지만 다른 컴파일러에서는 그렇지 않을 수 있습니다. Jon Skeet이 제안한대로 javap -c을 사용하는 것과 같이 디 컴파일을 통해 출력을 확인하는 것이 유일한 방법입니다.

0

나는 두번째 예를 들어 너무

제거됩니다 볼이 있었다 내 수업

public class Test { 

    public static void main(String[] args) throws Exception{ 
     final int VALUE = 3; 
     if (VALUE > 9) System.out.println("VALUE > 9 ???"); 
    } 
} 

이 내가 몇 가지 테스트를 실행하고 보인다 버전

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

public static void main(java.lang.String[]) throws java.lang.Exception; 
    Code: 
    0: return 

} 
4

을 디 컴파일한다 (논리적으로) 조건이 false로 평가되는 constant expression 인 경우 javac가 코드를 제거합니다.

요약하면, 상수 표현식은 상수 값으로 초기화 된 피연산자, 즉 프리미티브, 문자열 리터럴 및 final 프리미티브 또는 문자열 변수로만 상수를 사용하는 표현식입니다. 이 14.21 맨 아래에서 설명되는 바와 같이 그 스마트 컴파일러를 강제하지 않는다 JLS 같은 종속 컴파일러 것을

참고

좋은 컴파일러 실현있다가 문 X = 3; 실행되지 않으며 생성 된 클래스 파일에서 해당 명령문의 코드를 생략 할 수 있습니다.

+0

그것은 많은 감각을 불러 일으킬 것 같은데 ... 실제로 이것이 어딘가에서 문서에 명시되어 있는지 알고 있습니까? +1 –

+0

@ MarkusA. 내 편집을 참조하십시오. – assylias

+0

제공하신 링크와 정보에 대한 답을 작성했습니다. 나는 이것이 더 완전하고/명백한 방법이라고 믿는다. 그러나 나는 여전히 당신이 처음에 관련 빌딩 블록을 제공 할 자격이 있다고 생각합니다. 그래서, 한 번 더 대답을 업데이트하고 싶다면 (광산에서 부품을 복사하는 것이 자유 롭습니다), 대신에 당신의 답을 수락하고 광산을 제거 할 수 있는지 궁금합니다. :) –

0

내 생각에 이것은 구현에 따라 다릅니다 (Oracle, IBM, ...). 당신이 오라클의 버전, 오픈 JDK 프로젝트 될 자원을 찾고 시작하는 좋은 장소에 관심이 있다면

: 답을 발견 할 http://openjdk.java.net/groups/compiler/