[java] Java 메소드 선언의 최대 매개 변수 수

Java의 메소드가 가질 수있는 최대 매개 변수 수는 얼마이며 그 이유는 무엇입니까?

64 비트 Windows 시스템에서 Java 1.8을 사용하고 있습니다.

이에 대한 StackOverflow의 모든 답변은 기술적 한계가 이유를 지정하지 않고 255 개의 매개 변수라고 말합니다.

정확히 말하면, 255는 정적 인 경우와 254는 비 정적 ( this이 경우 255 번째) 방법입니다.

나는 이것이 일종의 사양으로 설명 될 수 있다고 생각했으며 허용 된 최대 수의 매개 변수가 정적으로 정의되어 있다고 생각했습니다.

그러나 이것은 int모든 4 바이트 유형 에만 유효합니다 . long매개 변수로 몇 가지 테스트 를 수행 했으며이 경우 127 개의 매개 변수 만 선언 할 수있었습니다.

String매개 변수를 사용하면 테스트에서 추론 한 허용 숫자는 255입니다 (Java에서 참조 크기가 4 바이트이기 때문일 수 있습니다).

그러나 64 비트 시스템을 사용하고 있으므로 참조 크기는 8 바이트이어야하며 String매개 변수의 경우 허용되는 최대 수는 long유형 과 비슷한 127이어야합니다 .

이 한도는 어떻게 정확하게 적용됩니까?

한계가 메소드 의 스택 크기 와 관련이 있습니까?

참고 : 실제로 모든 방법에서 이러한 많은 매개 변수를 사용하지는 않지만이 질문은 정확한 동작을 명확하게하기위한 것입니다.



답변

이 제한은 JVM 사양에 정의되어 있습니다 .

메소드 매개 변수의 수는 메소드 디스크립터 (§4.3.3)의 정의에 의해 255 로 제한되며, 여기서 한계는 인스턴스 또는 인터페이스 메소드 호출의 경우 이를 위해 하나의 단위를 포함 합니다.

§4.3.3에는 몇 가지 추가 정보가 있습니다.

방법 설명은 그 길이에 대한 기여를 포함하고 255 이하의 총 길이와 메소드 파라미터 나타내는 경우에만 유효 인스턴스 또는 인터페이스 메소드 호출의 경우에이.

총 길이는 개별 매개 변수의 기여를 합산하여 계산됩니다. 여기서 long 또는 double 유형의 매개 변수는 길이에 두 단위를 기여하고 다른 유형의 매개 변수는 하나의 단위를 기여 합니다.

두 단어의 기본 요소 ( long/ double)는 일반적인 4 바이트 변수 와 4 바이트 객체 인스턴스 참조 의 두 배 크기가 필요합니다 .

64 비트 시스템과 관련된 질문의 마지막 부분과 관련하여 사양은 매개 변수가 기여하는 단위 수를 정의하며 사양의 일부 는 64 비트 플랫폼에서도 계속 준수해야 합니다 .64 비트 JVM은 255 개의 인스턴스 매개 변수 (255와 같은)를 수용합니다 Strings) 내부 객체의 포인터 크기에 관계없이


답변

JVM 스펙의 4.3.3 절 에는 찾고있는 정보가 있습니다.

메소드 디스크립터는 총 길이가 255 이하인 메소드 매개 변수를 나타내는 경우에만 유효하며,이 길이에는 인스턴스 또는 인터페이스 메소드 호출의 경우에 대한 기여가 포함됩니다. 총 길이는 개별 매개 변수의 기여를 합산하여 계산됩니다. 여기서 long 또는 double 유형 의 매개 변수 는 길이 에 두 단위 기여하고 다른 유형 매개 변수는 하나의 단위를 기여 합니다.

따라서 호스트 시스템이 32 비트인지 64 비트인지 여부는 매개 변수 수에 영향을 미치지 않습니다. 알다시피, 문서는 “단위”로 말하며, 여기서 “단위”의 길이는 단어 크기의 함수입니다. 매개 변수 수가 단어 크기에 직접 비례하는 경우 이식성 문제가 있습니다. 다른 아키텍처에서 동일한 Java 프로그램을 컴파일 할 수 없습니다 (적어도 하나의 메소드가 더 큰 단어 크기로 아키텍처에서 최대 수의 매개 변수를 사용했다고 가정).


답변

이에 관한 뉴스 레터에서 흥미로운 문제를 발견했습니다. http://www.javaspecialists.eu/archive/Issue059.html

클래스 별 또는 인터페이스 당 상수 풀은 ClassFile 구조의 16 비트 constant_pool_count 필드에 의해 65535 개의 항목으로 제한됩니다. 이는 단일 클래스 또는 인터페이스의 총 복잡성에 대한 내부 제한으로 작동합니다. 기본이 아닌 비 추상적 메서드 당 코드의 양은 Code 특성의 exception_table, LineNumberTable 특성 및 LocalVariableTable 특성의 인덱스 크기에 따라 65536 바이트로 제한됩니다.

메소드 호출시 작성된 프레임의 로컬 변수 배열에서 로컬 변수의 최대 수는 메소드 코드를 제공하는 Code 속성의 max_locals 항목 크기에 따라 65535로 제한됩니다. long 및 double 유형의 값은 각각 두 개의 로컬 변수를 예약하고 max_locals 값에 두 개의 단위를 제공하는 것으로 간주되므로 해당 유형의 로컬 변수를 사용하면이 한계가 더 줄어 듭니다.

클래스 또는 인터페이스에 의해 선언 될 수있는 필드 수는 ClassFile 구조의 fields_count 항목 크기에 따라 65535로 제한됩니다. ClassFile 구조의 fields_count 항목 값에는 수퍼 클래스 또는 수퍼 인터페이스에서 상속 된 필드가 포함되지 않습니다.


답변