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


82

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

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


4
거대한 두뇌 코드를 컴파일하려고 할 때도 같은 문제에 직면했습니다.
johnchen902

3
반대되는 정보가 주어지지 않으면이 제한이 Java 8에서 계속 적용된다고 가정하는 것이 안전하다고 생각합니다. 물론 또 다른 (비용이 많이 드는) 옵션은 parboiled 에 대한 문법 엔진을 변경하는 것입니다. 순수 Java로 문법을 작성하십시오.
fge 2013-07-02

4
기사를 보라
Anirudha 2013-07-02

7
개인적으로 그렇게 큰 메소드를 만드는 것은 JavaCC버그 라고 생각 합니다. 정말로 코드를 퍼뜨릴 수 있어야합니다. 특히 JVM이 이러한 거대한 방법을 최적화하기 위해 구축되지 않았다는 점을 고려하면 더욱 그렇습니다.
Joachim Sauer 2013

답변:


58

JVMS7 에 따르면 :

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

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

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


2
아직도 수정되지 않은 자바에 그런 "버그"가 있는가? 특히 LaurentG 상황의 경우 큰 제한이 될 수 있습니다.
Francesco Belladonna 2013

3
@ Fire-Dragon-DoL 인용 된 논의는 다른 방법 보다 길이가 1 바이트 적어야 한다는 것입니다. 이것은 매우 중요하지 않습니다. 제한은 이와 같은 단순한 "버그"때문이 아닙니다. 바이트 코드전체 디자인에 있으며이를 수정 하려면 전체를 다시 지정해야합니다.
Marko Topolnik 2014

11

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

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

건배,


5
"최대 지역 변수 수"는 동일한 수치를 가지지 만 여전히 "방법의 최대 크기"와는 완전히 다른 것으로 OP가 요청했습니다.
Holger

8

변경되지 않았습니다. 메소드의 코드 제한은 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보다 작아야합니다.


1

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

jvms 에서 인용 :

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

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


-1

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

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