19

최근 Eclipse의 Java 컴파일러를 사용하기 시작했습니다. 표준 javac보다 훨씬 빠르기 때문입니다. 증분 컴파일을 수행하기 때문에 속도가 더 빠르다고 들었습니다. 하지만 eclispse와 sun 's 컴파일러 모두에 대한 권위있는 문서를 찾을 수 없기 때문에이 점에 대해서는 아직 확신이 없습니다. Sun의 컴파일러가 항상 모든 소스 파일을 컴파일하고 Eclipse의 컴파일러가 변경된 파일과 변경에 의해 영향을받는 파일 만 컴파일하는 것은 사실입니까?표준 Sun Java는 증분 컴파일을 수행 할 수 있습니까?

편집 : 나는 이클립스 자동 빌드 기능을 사용하지 않는하지만 내 개미 빌드 대신 내가

-Dbuild.compiler=org.eclipse.jdt.core.JDTCompilerAdapter 

를 설정하고있다.

+1

오라클은'sjavac' 도구로이를 해결하기 위해 노력했습니다. 관련 질문 : http://stackoverflow.com/questions/26424759/what-is-sjavac-who-is-it-for-and-how-do-i-use-it – aioobe

답변

14

Sun의 컴파일러는 항상 모든 소스 파일을 컴파일하고 Eclipse의 컴파일러는 컴파일 만 변경하는 것이 사실입니까? 파일 및 영향을받는 파일 그런 변화로?

나는 두 가지 모두에 대해 정확하다고 생각합니다.

물론 Eclipse가 모든 것을 다시 컴파일하도록 할 수 있습니다.

그러나 방정식의 다른 부분은 Ant 및 Maven과 같은 Java 빌드 도구가 변경된 클래스와 종속 클래스 트리 만 컴파일 할 수 있다는 것입니다. 기본적으로

  • <javac> task.java의 타임 스탬프와 .class 파일을 해당 비교, 오직 자바 컴파일러를 알려줍니다 :

    편집 개미에서

    , 증분 컴파일은 두 가지 방법으로 수행 할 수 있습니다 해당 대상 (.class) 파일보다 최신 파일이거나 대상 파일이 전혀없는 원본 (.java) 파일을 다시 컴파일하십시오.

  • <depend> task도 클래스 간 종속성을 고려하여 .class 파일에 포함 된 종속성 정보를 읽고 분석하여 결정합니다. 어느 .class 파일이 오래된 것인지 확인한 후 <depend> 작업은 해당 파일을 삭제하므로 다음 <javac> 작업이 해당 파일을 다시 컴파일합니다. 그러나 이것은 완전히 바보가 아닙니다. 예를 들어 소스 코드를 크게 변경하면 <depend> 작업이 부실한 종속성을 분석하게 될 수 있습니다. 또한 특정 종류의 종속성 (예 : 정적 상수)은 .class 파일 형식에서 분명하지 않습니다.

    개미 <depend>이 어리석지 않은 이유를 이해하려면 documentation의 "제한 사항"섹션을 읽어보십시오.

+0

Ant와 함께 부분 컴파일하는 방법을 설명 할 수 있습니까? 작업? Ant는 변경된 파일 만 컴파일하고 소스 트리의 다른 파일을 무시하도록 Sun의 컴파일러를 어떻게 강제합니까? –

+0

나는 당신이 나의 원래 질문에 대답했다고 생각하지만, 더 많은 정보를 제공함에 따라 나는 더욱 혼란스러워진다. 그것이 올바르게 이해된다면 이전 타임 스탬프가 변경되지 않으면 종속 클래스를 컴파일하지 않기 때문에 이전 클린이없는 javac 작업은 매우 위험한 작업입니다. (우습게, 어제 propably이 어제 문제가 있다는 것을 깨달았습니다. 내게 총 신비처럼 보였습니다.) –

+0

종속 클래스가 변경되지 않은 경우 왜 컴파일해야합니까? –

2

이클립스 확실히 않습니다. 또한 옵션을 켠 경우에는 저장시 시간이 절약됩니다 (기본적으로 설정되어 있습니다). 해가 또한 그렇게하지 않는 것처럼 보입니다. (테스트하기 쉽습니다. A가 B 클래스를 사용하는 메인 클래스이지만 B가 A 클래스를 사용하지 않는 작은 프로젝트를 만듭니다. 그런 다음 A를 변경하고 프로젝트를 컴파일하십시오. 다시 b.class의 타임 스탬프가 변경되었는지 확인하십시오

이것은 많은 컴파일러가 작동하는 방식입니다 (예 : gcc). ant 및 make와 같은 도구를 사용하여 변경된 프로젝트 만 컴파일 할 수 있습니다. 이 도구들이 완벽하지는 않으며 때로는 일식이 변경 사항을 잃어 버리고 전체 재구성을해야합니다.

3

Javac은 명령 줄에서 이름이 지정되었거나 종속성이 있고 최신이 아닌 원본 파일 만 컴파일합니다. 이클립스는 그 의미를보다 세분화하여 결정할 수 있습니다.

+0

이 답변을 지원하는 일부 문서를 연결할 수 있습니까? 나는 1) 의존성이 평범한 javac에 의해 컴파일되지 않는다고 생각한다. 2) 이클립스는 완전히 다른 컴파일러이고, 더 정교한 결정 방법이 아니다. 나는 그것을 증명할 수는 없지만 그것이 내가 묻는 이유입니다.) ... –

+0

http://download.oracle.com/javase/6/docs/technotes/tools/windows/javac.html#searching. 물론 당신은 그것을 증명할 수 있습니다 : 제가 설명한 조건을 설정하면 당신 스스로 볼 수 있습니다. – EJP

+0

올바른 예입니다. javac는 "모든 소스 파일"이 아닌 컴파일하도록 지정한 파일을 컴파일합니다. 그것은 어떤 파일을 컴파일해야하는지 자체적으로 결정하지 않기 때문에 OP가 묻는 의미에서 점진적이지 않습니다. Javac이 클래스 A를 컴파일하고 A가 의존하는 다른 .java 파일을 발견하면 (EJP에서 말했듯이), 여러 요인에 따라 컴파일됩니다. 이것은 A.java의 변경에 영향을받을 수있는 파일을 찾는 것과 같지 않습니다. 사람들이 혼란스러워하는 곳이라고 생각합니다. – gatkin

2

내가 여기에 무슨 소리를 들었어요 재 언급하고 나처럼 게으른 사람들을 위해 그것을 같이 분석 :

당신은 증가 달성 할 수있는 것은 개미의 javac의 작업으로 구축,하지만 당신은 할 파일을을 .class 지우려면이 작업을 따라 사용해야합니다 수정 한 .java 그리고 javac 작업에서 includes 문을 지정하지 않은 채로 두지 마십시오. (javac 작업에서 src 경로 만 지정하고 지정하지 않은 경우 javac은 모든 소스를 다시 컴파일합니다.)

다음은 내 종속 및 javac 작업입니다. 표준 Oracle Java 컴파일러를 사용하면 수정 한 .java 파일 만 컴파일됩니다. 희망이 도움이!

<depend srcdir="JavaSource" destdir="${target.classes}" cache="${dependencies.dir}" closure="yes"> 
    <classpath refid="compiler.classpath" /> 
    <include name="**/*.java"/> 
</depend> 

<javac destdir="${target.classes}" debug="true" debuglevel="${debug.features}" optimize="${optimize.flag}" fork="yes" deprecation="no" source="1.6" target="1.6" encoding="UTF-8" includeantruntime="no"> 
    <classpath refid="compiler.classpath"/> 
    <src path="JavaSource"/> 
    <include name="**/*.java" /> <!-- This enables the incremental build --> 
</javac>