Java 코드 컴파일

JDT 플러그인에는 소스 코드에서 Java .class 파일을 빌드하는 증분 및 일괄처리 Java 컴파일러가 포함되어 있습니다. API는 컴파일러가 직접 제공하지 않으며, Java 프로젝트에 빌더로 설치됩니다. 컴파일은 표준 플랫폼 빌드 메커니즘을 사용하여 트리거됩니다.

플랫폼 빌드 메커니즘은 증분 프로젝트 빌더에서 자세히 설명합니다.

코드 컴파일

빌드 API를 사용하여 프로젝트의 Java 소스 파일을 프로그램에 따라 컴파일할 수 있습니다.

   IProject myProject;
IProgressMonitor myProgressMonitor;
myProject.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, myProgressMonitor);

Java 프로젝트에서는 이 코드가 Java 증분 프로젝트 빌더를 프로젝트의 빌드 스펙에 추가된 다른 증분 프로젝트 빌더와 함께 호출합니다. 생성된 .class 파일은 지정된 출력 폴더에 기록됩니다. 추가 자원 파일은 출력 폴더에도 복사됩니다. 

전체 일괄처리 빌드의 경우 출력 폴더에 있는 모든 .class 파일은 무효 파일이 없도록 '정리'될 수 있습니다. 이것은 JDT 코어 빌더 옵션 (CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER)을 사용하여 제어됩니다.  이 옵션의 기본값은 출력 폴더를 정리하는 것입니다.  이 옵션을 재설정하는 경우를 제외하고 해당 소스 파일이 없는 모든 .class 파일을 출력 폴더 대신 클래스 경로에 있는 별도의 클래스 파일 폴더에 놓아야 합니다.

증분 빌더 및 일괄처리 빌더는 출력 폴더에 복사하는 자원을 제어하는 다른 옵션을 사용하여 구성할 수 있습니다.  다음 샘플은 '.ignore'로 끝나는 파일과 이름이 'META-INF'인 폴더가 출력 폴더에 복사되지 않도록 하는 자원 필터를 설정하는 방법을 보여줍니다.

      Hashtable options = JavaCore.getOptions();
   options.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, "*.ignore,META-INF/");
   JavaCore.setOptions(options);

파일 이름은 제공된 패턴 중 하나와 일치할 경우 필터링됩니다. 전체 폴더는 폴더의 이름이 경로 분리자로 끝나는 제공된 폴더 이름 중 하나와 일치하는 경우 필터링됩니다.

.classpath 파일에 오류가 있을 때 단일 오류만 생성하도록 증분 및 일괄처리 빌더를 구성할 수도 있습니다. 이 옵션은 기본적으로 설정되며 많은 오류를 제거합니다.  빌더 관련 옵션 및 기본값의 전체 목록은 JDT 코어 빌더 옵션을 참조하십시오.

컴파일러는 JavaCore 옵션을 사용하여 구성될 수도 있습니다.  예를 들어, 컴파일 중 발생하는 여러 종류의 문제점에 사용해야 하는 심각도를 정의할 수 있습니다. 컴파일러 관련 옵션 및 기본값 전체 목록은 JDT 코어 컴파일러 옵션을 참조하십시오.

빌더 또는 컴파일러의 옵션을 프로그램에 따라 구성할 경우, 옵션 범위를 정해야 합니다.  예를 들어, 자원 필터를 설정하면 특정 프로젝트에만 적용될 수 있습니다.  다음 예제는 이전에 표시된 것과 같은 자원 필터를 설정하지만 개별 프로젝트만 설정합니다.

   
   Hashtable options = myProject.getOptions(false);  // get only the options set up in this project
   options.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, "*.ignore,META-INF/");
   myProject.setOptions(options);

일괄처리 컴파일러 사용

일괄처리 컴파일러 찾기

일괄처리 컴파일러 클래스는 JDT/코어 플러그인의 내부 클래스에 있습니다. 따라서 plugins/org.eclipse.jdt.core 디렉토리의 jdtcore.jar 파일에 있습니다. 클래스 이름은 org.eclipse.jdt.internal.compiler.batch.Main입니다.

일괄처리 컴파일러 실행

사용 가능한 옵션

오렌지색 배경으로 표시된 옵션이 제안된 옵션입니다.

이름 사용법
클래스 경로 옵션
-bootclasspath <dir 1>;<dir 2>;...;<dir P> 컴파일러에서 사용되는 클래스 파일을 부트스트랩하는 데 사용되는 디렉토리 또는 jar 파일 목록입니다. 기본적으로, 실행 중인 VM 라이브러리가 사용됩니다. 항목은 플랫폼 경로 분리자로 구분됩니다.
-cp
-classpath <dir 1>;<dir 2>;...;<dir P>
소스 파일을 컴파일하는 데 사용되는 디렉토리 또는 jar 파일 목록입니다. 기본값은 "java.class.path" 특성 값입니다. 항목은 플랫폼 경로 분리자로 구분됩니다.
-extdirs <dir 1>;<dir 2>;...;<dir P> 확장 zip/jar 파일의 위치를 지정하는 데 사용되는 디렉토리 목록입니다. 항목은 플랫폼 경로 분리자로 구분됩니다.
-sourcepath <dir 1>;<dir 2>;...;<dir P> 소스 파일을 지정하는 데 사용되는 디렉토리 목록입니다. 항목은 플랫폼 경로 분리자로 구분됩니다.
-d <dir 1>|none 생성된 .class 파일을 덤프해야 하는 디렉토리를 지정하는 데 사용됩니다. 이 옵션을 생략하면 패키지 디렉토리 구조가 작성되지 않습니다.
.class 파일을 생성하지 않으려면 -d none을 사용하십시오.
-encoding <encoding name> 기본 소스 인코딩 형식을 지정하십시오(각 입력 소스 파일/폴더 이름에 [encoding <encoding name>] 접미부를 추가하여 파일별로 사용자 정의 인코딩을 지정할 수도 있음).
준수 옵션
-target 1.1|1.2|1.3|1.4|1.5|5|5.0 .class 파일 대상 설정을 지정합니다. 가능한 값은 다음과 같습니다.
  • 1.1(주 버전: 45 부 버전: 3)
  • 1.2(주 버전: 46 부 버전: 0)
  • 1.3(주 버전: 47 부 버전: 0)
  • 1.4(주 버전: 48 부 버전: 0)
  • 1.5, 5 또는 5.0(주 버전: 49 부 버전: 0)
기본값은 다음과 같습니다.
  • 1.1(-1.3 모드에서)
  • 1.2(-1.4 모드에서)
  • 1.5(-1.5 모드에서)
-1.3 준수 레벨을 1.3으로 설정합니다. 암시적 -source 1.3 -target 1.1.
-1.4 준수 레벨을 1.4(기본값)로 설정합니다. 암시적 -source 1.3 -target 1.2.
-1.5 준수 레벨을 1.5로 설정합니다. 암시적 -source 1.5 -target 1.5.
-source 1.3|1.4|1.5|5|5.0 컴파일러의 소스 레벨을 사용하도록 하는 데 사용됩니다.
가능한 값은 다음과 같습니다.
  • 1.3
  • 1.4
  • 1.5, 5 또는 5.0
기본값은 다음과 같습니다.
  • 1.3(-1.3 모드에서)
  • 1.4(-1.4 모드에서)
  • 1.5(-1.5 모드에서)
1.4에서는 assert가 키워드로 간주됩니다. 1.5에서는 enumassert가 키워드로 간주됩니다.
경고 옵션
-warn:
allDeprecation
allJavadoc
assertIdentifier
boxing
charConcat
conditionAssign
constructorName
dep-ann
deprecation
emptyBlock
enumSwitch
fieldHiding
finalBound
finally
hiding
incomplete-switch
indirectStatic
intfAnnotation
intfNonInherited
javadoc
localHiding
maskedCatchBlocks
nls
noEffectAssign
null
over-ann
pkgDefaultMethod
semicolon
serial
specialParamHiding
static-access
staticReceiver
suppress
synthetic-access
syntheticAccess
tasks(<task1>|...|<taskN>)
typeHiding
unchecked
unnecessaryElse
unqualified-field-access
unqualifiedField
uselessTypeCheck
unused
unusedArgument
unusedImport
unusedLocal
unusedPrivate
unusedThrown
varargsCast
warningToken
경고 레벨을 설정하십시오.
예: -warn:unusedLocals,deprecation

빨간색으로 표시된 것은 기본 설정입니다.

    -warn:<warnings separated by ,>    enable exactly the listed warnings
    -warn:+<warnings separated by ,>   enable additional warnings
    -warn:-<warnings separated by ,>   disable specific warnings
allDeprecation 지원되지 않는 코드 내에서의 폐기
allJavadoc javadoc가 올바르지 않거나 누락됨
assertIdentifier assert가 ID로 사용됨
boxing 오토박싱(autoboxing) 변환
charConcat 문자 배열이 명시적으로 문자열로 변환되지 않고 문자열 연결에서 사용되는 경우
conditionAssign 부울 지정 가능성
constructorName 생성자 이름을 가진 메소드
dep-ann @Deprecated 어노테이션 누락
deprecation 지원되지 않는 코드 밖의 폐기된 유형 또는 구성원 사용
emptyBlock 문서화되지 않은 빈 블록
enumSwitch,
incomplete-switch
불완전한 열거 스위치
fieldHiding 다른 변수를 숨기는 필드
finalBound 최종 바인드된 유형 매개변수
finally finally 블록이 정상적으로 완료되지 않음
hiding fieldHiding, localHiding, typeHiding 및 maskedCatchBlock에 대한 매크로
indirectStatic Static 구성원에 대한 간접 참조
intfAnnotation 어노테이션 유형이 상위 인터페이스로 사용됨
intfNonInherited 인터페이스 비상속 메소드 호환성
javadoc 올바르지 않은 javadoc
localHiding 로컬 변수가 다른 변수를 숨김
maskedCatchBlocks 숨겨진 catch 블록
nls 비nls 문자열 리터럴(//$NON-NLS-<n> 태그 없음)
noEffectAssign 영향을 주지 않는 지정의 경우
null 누락된 또는 중복 널 검사
over-ann @Override 어노테이션 누락
pkgDefaultMethod 패키지 기본 메소드 대체 시도
serial serialVersionUID 누락
semicolon 불필요한 세미콜론 또는 빈 명령문
specialParamHiding 생성자 또는 setter 매개변수가 다른 필드를 숨김
static-access indirectStatic 및 staticReceiver에 대한 매크로
staticReceiver static 필드를 가져오거나 정적 메소드를 호출하는데 비정적 수신기가 사용되는 경우
suppress @SuppressWarnings 사용
syntheticAccess,
synthetic-access
내부 클래스에 대한 종합적 액세스 수행 시
tasks 소스 코드에서 tasks 태그에 대한 지원 사용
typeHiding 다른 유형을 숨기는 유형 매개변수
unchecked 선택되지 않은 유형 조작
unnecessaryElse 불필요한 else 절
unqualified-field-access,
unqualifiedField
필드에 대한 규정되지 않은 참조
unused unusedArgument, unusedImport, unusedLocal, unusedPrivate 및 unusedThrown에 대한 매크로
unusedArgument 사용하지 않는 메소드 인수
unusedImport 사용하지 않는 가져오기 참조
unusedLocal 사용하지 않는 로컬 변수
unusedPrivate 사용하지 않는 private 구성원 선언
unusedThrown 사용하지 않는 발생 예외 선언
uselessTypeCheck 불필요한 cast/instanceof 오퍼레이션
varargsCast varargs 인수가 필요로 하는 명시적 캐스트
warningToken @SuppressWarningsb에서 처리되지 않은 경고 토큰

-nowarn 경고 없음(-warn:none과 동일)
-deprecation -warn:deprecation과 동일.
디버그 옵션
-g[:none|:lines,vars,source] 디버그 속성 레벨을 설정하십시오.
-g 모든 디버그 정보(-g:lines,vars,source와 동일)
-g:none 디버그 정보 없음
-g:[lines,vars,source] 선택적 디버그 정보
-preserveAllLocals 디버그 목적으로 모든 로컬 변수를 보존하도록 컴파일러에 명시적으로 요청합니다. 이 옵션을 생략하면 컴파일러가 사용하지 않는 로컬을 제거합니다.
고급 옵션
@<file> 파일에서 명령행 인수를 읽습니다.
-maxProblems <n> 컴파일 단위당 최대 문제점 수(기본적으로 100개)
-log <filename> 컴파일러의 모든 출력을 덤프할 로그 파일을 지정하십시오. 이 옵션은 일괄처리 컴파일러를 디버그하거나 오류와 경고를 모두 포함하는 파일을 일괄처리 빌드에서 가져오려는 경우 아주 유용합니다. 확장자가 .xml인 경우, 생성되는 로그는 xml 파일입니다.
-proceedOnError 오류 시 컴파일을 계속하고 문제점 메소드 또는 문제점 유형을 사용하여 클래스 파일 덤프를 계속합니다. 남아 있는 오류가 있는 경우에도 응용프로그램을 실행할 수 있도록 하려는 경우에만 권장합니다.
-verbose 이 옵션을 지정하면 액세스된/처리된 컴파일 단위를 콘솔 또는 로그 파일에 인쇄합니다.
-referenceInfo 연산 참조 정보. 빌더에 연결된 경우에만 유용합니다. 그렇지 않은 경우 참조 정보는 쓸모가 없습니다.
-progress 진행 표시(-log 모드에서만).
-time 속도 정보 표시
-noExit 컴파일 종료 시 System.exit(n)을 호출하지 않음(오류가 없는 경우 n=0)
-repeat <n> 컴파일 프로세스를 <n>번 반복(성능 분석).
-inlineJSR 인라인 JSR 바이트 코드(대상 >= 1.5인 경우 암시적)
-enableJavadoc javadoc 내 참조 고려
도움말 옵션
-? -help 도움말 메시지를 표시합니다.
-v -version 컴파일러의 빌드 번호를 표시합니다. 버그를 보고하는 경우에 아주 유용합니다.
-showversion 컴파일러의 빌드 번호를 표시하고 계속합니다. 버그를 보고하는 경우에 아주 유용합니다.

예:

d:\temp -classpath rt.jar -time -g -d d:/tmp d:\temp 및 서브폴더의 모든 소스 파일을 컴파일합니다. 클래스 경로는 단지 rt.jar입니다. 모든 디버그 속성을 생성하며 생성된 모든 .class 파일은 d:\tmp에 덤프됩니다. 일괄처리 프로세스가 완료되면 컴파일러의 속도가 표시됩니다.
d:\temp\Test.java -classpath d:\temp;rt.jar -g:none Test.java만 컴파일하고 d:\temp에서 종속 파일을 검색합니다. 클래스 경로는 rt.jar 및 d:\temp입니다. 이는 d:\temp에서 먼저 모든 필수 클래스를 검색한 후 rt.jar에서 검색함을 의미합니다. 디버그 속성을 생성하지 않으며, 생성된 모든 .class 파일은 d:\tmp에 덤프됩니다.

Ant javac 어댑터 사용

Eclipse 컴파일러를 javac 어댑터를 사용하는 Ant 스크립트 내부에서 사용할 수 있습니다. Eclipse 컴파일러를 사용하려면 스크립트에 build.compiler 특성을 정의해야 합니다. 다음은 간단한 예제입니다.
<?xml version="1.0" encoding="UTF-8" ?>
<project name="compile" default="main" basedir="../.">

	<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>

	<property name="root" value="${basedir}/src"/>

	<property name="destdir" value="d:/temp/bin" />

	<target name="main">
		<javac srcdir="${root}" destdir="${destdir}" debug="on" nowarn="on" extdirs="d:/extdirs" source="1.4">
		    <classpath>
		      <pathelement location="${basedir}/../org.eclipse.jdt.core/bin"/>
		    </classpath>
		</javac>		
	</target>
</project> 
javac Ant 타스크에 사용된 구문은 Ant javac 타스크 문서에 있습니다. 현재 어댑터는 Javac Ant 타스크 1.4.1 - 1.6.5 버전을 지원합니다.

사용 중인 버전이 1.5.0 이상인 경우, 중첩된 컴파일러 인수 요소를 사용하여 컴파일러 특정 옵션을 지정할 수 있습니다.

...
		<javac srcdir="${root}" destdir="${destdir}" debug="on" nowarn="on" extdirs="d:/extdirs" source="1.4">
		    <classpath>
		      <pathelement location="${basedir}/../org.eclipse.jdt.core/bin"/>
		    </classpath>
    <compilerarg compiler="org.eclipse.jdt.core.JDTCompilerAdapter" line="-1.5 -warn:+boxing"/>
</javac>		
...

컴파일러 종속 스크립트를 가져오지 않도록 하려면 컴파일러 인수를 org.eclipse.jdt.core.JDTCompilerAdapter로 설정하여 사용하는 것이 좋습니다. 이를 설정하지 않은 경우, 스크립트는 Eclipse 컴파일러하고만 사용할 수 있습니다. 설정은 했지만, 이름이 build.compiler 특성으로 지정된 컴파일러 이름과 다른 경우 중첩된 컴파일러 인수는 무시됩니다.

문제점 판별

JDT 코어는 특수 마커(마커 유형 "org.eclipse.jdt.core.problem")를 정의하여 컴파일 문제점을 선언합니다. 컴파일러가 발견한 문제점을 프로그램에 따라 찾으려면 표준 플랫폼 마커 프로토콜을 사용해야 합니다. 마커 사용에 대한 개요는 자원 마커를 참조하십시오.

다음 스니펫은 컴파일 단위의 모든 Java 문제점 마커를 찾습니다.

   public IMarker[] findJavaProblemMarkers(ICompilationUnit cu) 
         throws CoreException {
      IResource javaSourceFile = cu.getUnderlyingResource();
      IMarker[] markers = 
         javaSourceFile.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER,
            true, IResource.DEPTH_INFINITE);
   }

Java 문제점 마커는 Java 프로젝트 빌더가 유지보수하며, 문제점이 분석되고 Java 소스가 다시 컴파일될 때 자동으로 제거됩니다.

문제점 ID 값은 IProblem에 있는 상수 중 하나로 설정합니다. 문제점의 ID는 확실하지만 메시지는 번역되므로 기본 로케일에 따라 변경될 수 있습니다. IProblem에 정의된 상수는 자체 설명적입니다.

Java 조작 중 발견된 문제점을 수집하려면 IProblemRequestor의 구현을 정의해야 합니다. 작업 중인 사본 생성에 대해 IProblemRequestor를 제공한 경우 작업 중인 사본은 문제점 탐지를 수용할 수 있습니다. 이것을 수행하기 위해 reconcile 메소드를 사용할 수 있습니다. 다음은 특성 보기의 예제입니다.

  ICompilationUnit unit = ..; // get some compilation unit
			
  // create requestor for accumulating discovered problems
  IProblemRequestor problemRequestor = new IProblemRequestor() {
    public void acceptProblem(IProblem problem) {
      System.out.println(problem.getID() + ": " + problem.getMessage());
    }
    public void beginReporting() {}
    public void endReporting() {}
    public boolean isActive() {	return true; } // will detect problems if active
  };
    
  // use working copy to hold source with error
  ICompilationUnit workingCopy = unit.getWorkingCopy(new WorkingCopyOwner() {}, problemRequestor, null);
  ((IOpenable)workingCopy).getBuffer().setContents("public class X extends Zork {}");

  // trigger reconciliation			
  workingCopy.reconcile(NO_AST, true, null, null);
acceptProblem(IProblem) 메소드에 보고된 문제점에 대한 조치를 추가할 수 있습니다. 이 예제에서 보고된 문제는 Zork를 분석할 수 없거나 Zork가 올바른 수퍼클래스가 아니고 Zork의 ID가 IProblem.SuperclassNotFound라는 점입니다.