Java AOT 컴파일러는 어떻게 작동합니까?


18

Java 앱을 기본 실행 파일 ( ) 로 변환한다고 주장 하는 몇 가지 도구 ( Excelsior JET 등)가 *.exe있습니다. 그러나이 도구가 실제로 쉘 또는 명령 줄에서 호출 / 실행하는 기본 래퍼를 만드는 것임을 이해 합니다 java.

그 이해가 정확하지 않으면 어떻게 될 수 있는지 알 수 없습니다. 실행중인 JVM ( java프로세스)이 본질적으로 고성능 클래스로 Java 클래스 파일에서 바이트 코드를 즉시로드하는 경우 Java 응용 프로그램 (JVM에 입력 역할을하는 바이트 코드 파일 모음)이 어떻게 작동하는지 알 수 없습니다 실제로 실행 파일로 변환되었습니다.

JVM 프로세스는 이미 바이트 코드 파일 세트를 입력으로 사용하는 기본 실행 파일 이기 때문 입니다. 바이트 코드 파일과 JVM 프로세스를 단일 통합 기본 실행 파일로 병합하는 것은 JVM을 완전히 다시 작성하고 JVM 사양에서 탈선하지 않으면 불가능한 것 같습니다.

그래서 나는 묻습니다.이 도구들이 실제로 어떻게 자바 클래스 파일을 원시 실행 파일로 "변환"합니까?

답변:


26

모든 프로그램에는 런타임 환경이 있습니다. 우리는 이것을 잊는 경향이 있지만 거기에 있습니다. 운영 체제에 대한 시스템 호출을 래핑하는 C 용 표준 lib. Objective-C에는 모든 메시지 전달을 래핑하는 런타임이 있습니다.

Java에서 런타임은 JVM입니다. 사람들이 익숙한 대부분의 Java 구현은 바이트 코드 인터프리터 및 JIT 컴파일러 인 HotSpot JVM과 유사합니다.

이것이 유일한 구현 일 필요는 없습니다. Java 용 표준 lib-esque 런타임을 빌드 할 수없고 코드를 원시 머신 코드로 컴파일하고 런타임에서 새 오브젝트에 대한 호출을 malloc에 ​​대한 처리 및 파일을 시스템의 시스템 호출에 대한 파일 액세스를 처리하는 런타임 내에서 실행할 수 없다는 말은 전혀 없습니다. 이것이 바로 AIT Of Time (JIT 대신 AOT) 컴파일러가하는 일입니다. 당신은 ... 당신은 JVM 구현을 부를 수있는 무슨이 런타임에 전화 (그것은 않습니다 JVM을 사양에 따라) 자바 또는 런타임 환경 또는 표준 lib 디렉토리. 거기에 있고 본질적으로 같은 일을합니다.

javac네이티브 머신을 대상으로하기 위해 다시 구현 하여 수행 할 수 있습니다 ( GCJ 가 수행 한 작업). 또는 생성 된 javac바이트 코드를 다른 컴퓨터의 컴퓨터 (또는 바이트) 코드로 변환하여 수행 할 수 있습니다 .Android가 수행하는 작업입니다 . Wikipedia 를 기반으로 하는 Excelsior JET의 기능 ( "컴파일러는 이식 가능한 Java 바이트 코드를 원하는 하드웨어 및 운영 체제 (OS)에 최적화 된 실행 파일로 변환")이며 RoboVM 도 마찬가지입니다 .

Java와의 추가 합병증이 있으므로 독점적 접근 방식으로 수행 하기가 매우 어렵습니다. 클래스 ( class.forName()) 또는 프록시 객체 의 동적로드에는 AOT 컴파일러가 쉽게 제공 할 수없는 동적 요소가 필요하므로 각 JVM에는 JIT 컴파일러 (Excelsior JET) 또는 인터프리터 (GCJ)가 포함되어 있어야 사전 컴파일 할 수없는 클래스를 처리 할 수 ​​있습니다 원주민.

기억 JVM은 사양입니다 , 많은 구현과 함께 . C 표준 라이브러리는 다양한 구현이 포함 된 사양이기도합니다 .

Java8에서는 AOT 컴파일에 대한 약간의 작업이 수행되었습니다. 기껏해야 텍스트 상자의 범위 내에서만 일반적으로 AOT를 요약 할 수 있습니다. 그러나 2015 년 JVM 언어 서밋 (2015 년 8 월)에서 Java Goes AOT (youtube 비디오) 프레젠테이션이있었습니다 . 이 비디오는 40 분 길이이며 더 심도 깊은 기술적 측면과 성능 벤치 마크에 대해 설명합니다.


죄송합니다, 이것에 대해 잘 모르지만 이것이 java가 현재 네이티브라는 것을 의미합니까? 또는 원하는 경우 Java 프로그램을 원시 코드로 컴파일 할 수있는 새로운 컴파일러 플래그가 있으며 바이트 코드로 컴파일 할 수있는 옵션이 여전히 있습니까?
Pavel

@ paulpaul1076 내가 연결 한 비디오를 보는 것이 좋습니다. 의견에 합리적으로 맞을 수있는 것보다 훨씬 더 많이 있습니다.

4

gcj 최소한의 실행 가능한 예

또한 gcj(현재 사용되지 않는) 오픈 소스 구현을 관찰 할 수도 있습니다 . 예 : Java 파일 :

public class Main {
    public static void main(String args[]) {
        System.out.println("hello world");
    }
}

그런 다음 컴파일하고 실행하십시오.

gcj -c Main.java
gcj --main=Main -o Main Main.o
./Main

이제 자유롭게 디 컴파일하고 작동 방식을 확인할 수 있습니다.

file Main.o 엘프 파일이라고 말합니다.

readelf -d Main | grep NEEDED 동적 라이브러리에 따라 다릅니다.

0x0000000000000001 (NEEDED)             Shared library: [libgcj.so.14]
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

따라서 libgcj.so 는 Java 기능이 구현되는 위치에 있어야합니다.

그런 다음 다음을 사용하여 디 컴파일 할 수 있습니다.

objdump -Cdr Main.o

정확히 어떻게 구현되는지 봅니다.

이름 맹 글링과 간접 다형성 함수 호출이 많은 C ++처럼 보입니다.

가비지 수집이 어떻게 시작되는지 궁금합니다. /programming/7100776/garbage-collection-implementation-in-compiled-languages 및 Go와 같은 GC를 사용하는 다른 컴파일 된 언어를 살펴볼 가치가 있습니다 .

Ubuntu 14.04, GCC 4.8.4에서 테스트되었습니다.

또한 Android 5 이상의 백본 인 https://en.wikipedia.org/wiki/Android_Runtime을 살펴보고 Android 앱을 최적화하기 위해 전체 AOT를 수행하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.