[java] Java 7 및 8에서 메소드의 최대 크기

Java에서는 메서드가 64KB보다 클 수 없다는 것을 알고 있습니다. 이 제한으로 인해 JavaCC 문법 에서 생성 된 코드에 문제가 발생합니다 . Java 6에 문제가 있었고 문법을 변경하여이 문제를 해결할 수있었습니다. Java 7에 대한 제한이 변경되었거나 Java 8에 대한 계획입니까?

명확하게하기 위해서. 혼자서 64KB보다 큰 메서드는 필요하지 않습니다. 그러나 저는 매우 큰 방법으로 컴파일되는 문법을 썼습니다.



답변

JVMS7 에 따르면 :

end_pc가 배타적이라는 사실은 Java 가상 머신 설계의 역사적 실수입니다. 메소드의 Java 가상 머신 코드 길이가 정확히 65535 바이트이고 길이가 1 바이트 인 명령어로 끝나면 해당 명령어를 보호 할 수 없습니다. 예외 핸들러에 의해. 컴파일러 작성자는 메소드, 인스턴스 초기화 메소드 또는 정적 이니셜 라이저 (모든 코드 배열의 크기)에 대해 생성 된 Java 가상 머신 코드의 최대 크기를 65534 바이트로 제한하여이 버그를 해결할 수 있습니다.

그러나 이것은 약 Java 7. Java 8에 대한 최종 사양이 없으므로 개발자를 제외한 누구도이 질문에 답할 수 없습니다.

UPD (2015년 4월 6일) 에 따르면 JVM8 또한 마찬가지입니다 Java 8.


답변

좋은 질문. 항상 그렇듯이 소스 로 가서 답을 찾아야합니다 ( “Java® Virtual Machine 사양” ). 이 섹션에서는 제한 (Java6 VM 사양과 마찬가지로)을 명시 적으로 언급하지 않지만 다소 신중하게 설명합니다.

메서드 (§2.6) 호출시 생성 된 프레임의 지역 변수 배열에서 최대 지역 변수 수는 코드 속성 (§4.7.3)의 max_locals 항목 크기에 따라 65535 개로 제한됩니다. 메소드 및 Java Virtual Machine 명령어 세트의 16 비트 로컬 변수 인덱싱을 사용합니다.

건배,


답변

변경되지 않았습니다. 메소드의 코드 제한은 Java 7 및 Java 8 모두에서 여전히 64KB입니다.

참조 :

  1. Java 7 Virtual Machine Specification ( 4.9.1 Static Constraints )에서 :

클래스 파일의 Java Virtual Machine 코드에 대한 정적 제약은 Java Virtual Machine 명령어를 코드 배열에 배치하는 방법과 개별 명령어의 피연산자가 무엇이어야하는지 지정합니다.

코드 배열의 명령어에 대한 정적 제약은 다음과 같습니다.

  • 코드 배열은 비워 둘 수 없으므로 code_length 항목은 0 값을 가질 수 없습니다.
  • code_length 항목의 값은 65536보다 작아야합니다.
  1. Java 8 가상 머신 사양 ( 4.7.3 코드 속성 )에서 :

code_length 항목의 값은이 메서드에 대한 코드 배열의 바이트 수를 제공합니다.

code_length의 값은 0보다 크고 (코드 배열이 비어 있지 않아야하므로) 65536보다 작아야합니다.


답변

Andremoniy는 이미이 질문의 java 7일부에 답변했지만, 그 당시 결정을 내릴 때가 된 것 java 8같으므로 해당 부분을 다루기 위해 답변을 완성했습니다.

jvms 에서 인용 :

end_pc가 배타적이라는 사실은 Java Virtual Machine 설계의 역사적 실수입니다. 메소드의 Java Virtual Machine 코드 길이가 정확히 65535 바이트이고 길이가 1 바이트 인 명령어로 끝나면 해당 명령어를 보호 할 수 없습니다. 예외 핸들러에 의해. 컴파일러 작성자는 메소드, 인스턴스 초기화 메소드 또는 정적 초기화 프로그램 (코드 배열의 크기)에 대해 생성 된 Java Virtual Machine 코드의 최대 크기를 65534 바이트로 제한하여이 버그를 해결할 수 있습니다.

보시다시피이 역사적인 문제는 적어도이 버전 (Java 8)에서는 해결되지 않는 것 같습니다.


답변

해결 방법으로 파서의 코드에 대한 액세스 권한이있는 경우 ‘JVM 컴파일러에 의해 부과 된 한계’내에서 작동하도록 수정할 수 있습니다. (파서 코드에서 수정)


답변