source

Java 8 코드를 Java 7 JVM에서 실행하도록 컴파일할 수 있습니까?

gigabyte 2022. 8. 15. 21:24
반응형

Java 8 코드를 Java 7 JVM에서 실행하도록 컴파일할 수 있습니까?

Java 8은 람다 표현과 같은 중요한 새로운 언어 기능을 도입합니다.

이러한 언어 변경은 컴파일된 바이트 코드의 중대한 변경에 따른 것이어서 Java 7 가상 머신에서 역번역기를 사용하지 않고 실행할 수 없는 것입니까?

아니요. 소스 코드에서 1.8 기능을 사용하려면 1.8 VM을 대상으로 해야 합니다.저는 단지 새로운 Java 8 릴리스를 사용해 보고 컴파일을 시도했습니다.-target 1.7 -source 1.8컴파일러는 다음을 거부합니다.

$ javac Test -source 1.8 -target 1.7
javac: source release 1.8 requires target release 1.8

기본 방식에서는 Java 7에서는 불가능했던 바이트 코드와 JVM을 변경해야 합니다.Java 7 이하의 바이트 코드 검증자는 메서드 본문을 가진 인터페이스를 거부합니다(스태틱 이니셜라이저 메서드는 제외).디폴트 메서드는 서브클래스로 덮어쓸 수 있기 때문에 발신측에서 스태틱메서드를 사용하여 에뮬레이트하려고 해도 같은 결과를 얻을 수 없습니다.Retrolambda는 기본 메서드의 백포트를 제한하지만 새로운 JVM 기능이 필요하기 때문에 완전히 백포트를 할 수 없습니다.

필요한 API 클래스가 Java 7에 존재한다면 람다스는 현재 상태로 실행할 수 있습니다.호출된ynamic 명령어는 Java 7에 존재하지만 컴파일 시에 lamda 클래스를 생성하도록 lamda를 구현할 수 있습니다(초기 JDK 8 빌드는 그렇게 했습니다). (Oracle은 향후 증명용으로 lamda에 대해 호출된ynamic을 사용하기로 결정했습니다.아마도 언젠가는 JVM이 최초로 lambda를 사용할 수 있을 것입니다.모든 람다에 대해 클래스를 생성하는 대신 ass 함수를 사용하도록 ass 함수를 변경하여 성능을 향상시킬 수 있습니다.)Retrolambda가 하는 일은 모든 호출된 명령어를 처리하여 익명 클래스로 대체하는 것입니다. 이는 Lamdba 호출된 명령어가 처음 호출되었을 때 Java 8이 실행 시 수행하는 것과 같습니다.

주석을 반복하는 것은 통사적인 설탕일 뿐이다.이전 버전과 호환되는 바이트 코드입니다.Java 7에서는 반복된 주석을 포함하는 컨테이너 주석의 구현 세부사항을 숨기는 도우미 메서드(: getAnnotationsByType)를 직접 구현하면 됩니다.

AFAIK, 타입 어노테이션은 컴파일 시에만 존재하므로 바이트 코드 변경이 필요하지 않으므로 Java 8 컴파일 클래스의 바이트 코드 버전 번호를 변경하는 것만으로 Java 7에서 동작할 수 있습니다.

메서드 파라미터명은 Java 7의 바이트코드에 존재하기 때문에 호환성이 있습니다.메서드의 바이트 코드를 읽고 메서드의 디버깅 정보에 있는 로컬 변수 이름을 보면 액세스 할 수 있습니다.예를 들어 Spring Framework는 @PathVariable을 구현하기 위해 정확하게 이 작업을 수행하므로 호출할 수 있는 라이브러리 메서드가 있을 수 있습니다.추상 인터페이스 메서드에는 메서드 본체가 없기 때문에 Java 7에서는 디버깅 정보가 존재하지 않으며 Java 8에서는 AFAIK도 존재하지 않습니다.

다른 신기능은 대부분 새로운 API, HotSpot의 개선, 툴링입니다.새로운 API 중 일부는 서드파티 라이브러리로 사용할 수 있습니다(예:ThreeTen-Backport스트림 지원).

요약하자면, 기본 메서드에는 새로운 JVM 기능이 필요하지만 다른 언어 기능은 필요하지 않습니다.그것들을 사용하려면 Java 8에서 코드를 컴파일한 후 Retrolambda의 바이트 코드를 Java 5/6/7 형식으로 변환해야 합니다.적어도 바이트 코드 버전을 변경해야 하며 javac은 이를 허용하지 않습니다.-source 1.8 -target 1.7역번역기가 필요합니다.

제가 알기로는 JDK 8의 이러한 변경 중 새로운 바이트 코드를 추가할 필요가 없었습니다.람다 계측기의 일부는 다음을 사용하여 수행되고 있습니다.invokeDynamic(JDK 7에 이미 존재합니다).따라서 JVM 명령 집합의 관점에서 보면 코드베이스가 호환되지 않는 것은 없습니다.단, API와 컴파일러에 관련된 많은 개선사항이 있어 이전 JDK에서 JDK8의 코드를 컴파일/실행하기 어려울 수 있습니다(그러나 저는 이것을 시도하지 않았습니다).

다음 참조 자료는 람다와 관련된 변화가 어떻게 계측되고 있는지에 대한 이해를 높이는 데 도움이 될 수 있습니다.

이것들은 사물들이 후드 아래에서 어떻게 계장되는지를 자세히 설명해준다.아마도 당신은 그곳에서 당신의 질문에 대한 답을 찾을 수 있을 것이다.

만약 당신이"retrotranslator"시험을 기꺼이 사용하려는 에스코 Luontola의 우수한 Retrolambda:https://github.com/orfjackal/retrolambda.

할수있습니다-source 1.7 -target 1.7그렇다면 컴파일할 것이다.만약 당신이 lambdas 등 8개 특정 기능 java 하지만 컴파일하지 않을 것이다.

언급URL:https://stackoverflow.com/questions/16143684/can-java-8-code-be-compiled-to-run-on-java-7-jvm

반응형