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


133

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이어야합니다 .

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

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

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


39
7, 가독성으로 미쳐 가고 싶지 않다면. (나는 당신이 실제로 무엇을 요구하는지 알고 있습니다).
Adam

14
나는 주장 할 것이다 <= 4. 더 많은 것은 아마도 객체로 싸야 할 것입니다.
Vivin Paliath 2016 년

4
이것이 왜 흥미로운 질문입니까? 프로그램을 작성 중이고이 한계에 도달하면 디자인이 잘못되었습니다. 왜 그렇게 쓸모없는 질문이 그렇게 많은 투표를 받는지 이해가되지 않습니다.
Jesper

20
@Jesper는 JVM 스펙에 대한 지식에 의문을 제기하기 때문에. 이 질문은 "이것이나 저것을하는 방법?"을 묻지 않습니다. 대신 "왜 내가 그것을 필요로 하는가?"라는 질문을합니다. +1 흥미로운 질문 Userv
Amit

2
@ 내가 생각한 것을 정확히 보라. OP는 방금 궁금했습니다.
Evan Carslake 2016 년

답변:


110

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

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

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

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

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

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

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


10
64 비트 아키텍처에서 스택도 64 비트라는이 답변에 추가하고 싶습니다. 따라서 매개 변수 수에 대한 제한은 스택 크기 바운드이므로 64 비트 스택은 동일한 255 개의 객체 참조를 저장할 수 있습니다. 특정의 치료 longdouble관계없이 시스템 아키텍처는 사양의 여러 곳에서 발생하고 32 비트 시대의 잔재 것으로 보인다.
Sergei

나는 그 부분을 편집하는 과정에 있었다 :) 동의, 다른 플랫폼에서도 스펙은 여전히 ​​존중되어야한다.
움베르토 RAIMONDI

1
예, 매개 변수의 수가 워드 크기의 함수라면 이식성이 떨어집니다. 다른 아키텍처에서 동일한 Java 프로그램을 성공적으로 컴파일 할 수 없습니다.
Vivin Paliath 2016 년

3
Varargs는 Object 배열 로 바뀌고 매개 변수 목록에서 한 번만 사용할 수 있으며 마지막 위치를 차지합니다. 이 모든 것을 고려할 때, varargs를 사용하면 매개 변수의 수를 254 + 정수로 확장 할 수 있다고 말하고 싶습니다 .MAX_VALUE (적어도 프로그래머에게는 ... 매개 변수는 여전히 255입니다). 그 트릭을 사용하면 정수를 가질 수 있습니다. MAX_VALUE 개의 객체 매개 변수.
움베르토 RAIMONDI

1
@MrTsjolder varargs에 대한 이 답변 을 살펴보십시오 .
Vivin Paliath 2016 년

11

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

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

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


10

이에 관한 뉴스 레터에서 흥미로운 문제를 발견했습니다. 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 항목 값에는 수퍼 클래스 또는 수퍼 인터페이스에서 상속 된 필드가 포함되지 않습니다.

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