Maksymalna liczba parametrów w deklaracji metody Java

133

Jaka jest maksymalna liczba parametrów, które może mieć metoda w Javie i dlaczego?

Używam języka Java 1.8 w 64-bitowym systemie Windows.

Wszystkie odpowiedzi na StackOverflow na ten temat mówią, że limit techniczny to 255 parametrów bez określenia dlaczego.

Dokładniej, 255 dla thismetod statycznych i 254 dla metod niestatycznych ( będzie to 255 w tym przypadku).

Pomyślałem, że można to opisać w jakiejś specyfikacji i że istnieje po prostu statycznie określona maksymalna liczba dozwolonych parametrów.

Ale dotyczyło to tylko inti wszystkich typów 4-bajtowych . Zrobiłem kilka testów z longparametrami i w tym przypadku byłem w stanie zadeklarować tylko 127 parametrów.

Z Stringparametrami dozwolona liczba, którą wydedukowałem z testów, to 255 (może to być spowodowane tym, że rozmiar odniesienia wynosi 4 bajty w Javie?).

Ale ponieważ używam systemu 64-bitowego, rozmiar referencji powinien mieć szerokość 8 bajtów, więc przy Stringparametrach maksymalna dozwolona liczba powinna wynosić 127, podobnie jak longtypy.

Jak dokładnie stosuje się ten limit?

Czy limit ma coś wspólnego z rozmiarem stosu metody?

Uwaga: tak naprawdę nie zamierzam używać tych wielu parametrów w żadnej metodzie, ale to pytanie ma na celu jedynie wyjaśnienie dokładnego zachowania.

userv
źródło
39
7, jeśli nie chcesz oszaleć z czytelnością. (Wiem, o co właściwie pytasz).
Adam
14
Spierałbym się <= 4. Coś więcej powinno być prawdopodobnie zawinięte w przedmiot.
Vivin Paliath
4
Dlaczego jest to interesujące pytanie? Jeśli piszesz program i osiągasz ten limit, twój projekt jest zły. Nie rozumiem, dlaczego tak praktycznie bezużyteczne pytanie spotyka się z tyloma pozytywnymi opiniami.
Jesper
20
@Jesper, ponieważ to kwestionuje znajomość specyfikacji JVM. To pytanie nie dotyczy „Jak zrobić to czy tamto?” zamiast tego pojawia się pytanie „Dlaczego tego potrzebuję?” ... +1 Ciekawe pytanie Userv
Amit
2
@amit dokładnie to, o czym myślałem. OP był po prostu zaciekawiony.
Evan Carslake

Odpowiedzi:

110

Limit ten jest określony w specyfikacji maszyny JVM :

Liczba parametrów metody jest ograniczona do 255 przez definicję deskryptora metody (§4.3.3), przy czym limit obejmuje jedną jednostkę na to w przypadku wywołań metod instancji lub interfejsu.

Sekcja §4.3.3 zawiera dodatkowe informacje:

Deskryptor metody jest prawidłowy tylko wtedy, gdy reprezentuje parametry metody o łącznej długości 255 lub mniej, gdzie ta długość obejmuje udział w tym w przypadku wywołań metod instancji lub interfejsu.

Całkowita długość jest obliczana poprzez zsumowanie wkładów poszczególnych parametrów, gdzie parametr typu long lub double dodaje dwie jednostki do długości, a parametr dowolnego innego typu - jedną jednostkę .

Twoje obserwacje były trafne, podwójne prymitywy słów ( long/ double) wymagają dwukrotnie większego rozmiaru niż zwykłe 4-bajtowe zmienne i 4-bajtowe odniesienia do instancji obiektu .

Jeśli chodzi o ostatnią część twojego pytania dotyczącego systemów 64-bitowych, specyfikacja określa, ile jednostek ma dany parametr , ta część specyfikacji musi być nadal przestrzegana nawet na platformie 64-bitowej, 64-bitowa maszyna JVM będzie obsługiwać 255 parametrów instancji (tak jak 255 Strings) niezależnie od rozmiaru wskaźnika obiektu wewnętrznego.

Umberto Raimondi
źródło
10
Dodałbym do tej odpowiedzi, że w architekturze 64-bitowej stos jest również 64-bitowy. Tak więc, ponieważ ograniczenie liczby parametrów jest związane z rozmiarem stosu, 64-bitowy stos umożliwia przechowywanie tych samych 255 odwołań do obiektów. Specyficzne traktowanie longi doubleniezależnie od architektury systemu występuje w wielu miejscach specyfikacji i wydaje się być pozostałością po ery 32-bitowej.
Siergiej
Byłem w trakcie edycji tylko tej części :) Zgoda, specyfikacja musi być nadal przestrzegana, nawet na różnych platformach.
Umberto Raimondi
1
Tak, jeśli liczba parametrów byłaby funkcją rozmiaru słowa, to zrujnowałoby przenośność; nie można było pomyślnie skompilować tego samego programu Java na różnych architekturach.
Vivin Paliath
3
Varargs są przekształcane w tablicę Object , mogą być użyte tylko raz na liście parametrów i zajmują ostatnią pozycję. Biorąc to wszystko pod uwagę, powiedziałbym, że używając varargs liczbę parametrów można "rozszerzyć" do 254 + Integer.MAX_VALUE (przynajmniej dla programisty ... parametry nadal wynoszą 255), więc używając tej sztuczki możesz mieć Integer. MAX_VALUE parametrów obiektu.
Umberto Raimondi
1
@MrTsjolder Spójrz na tę odpowiedź dla varargs.
Vivin Paliath
11

Sekcja 4.3.3 specyfikacji maszyny JVM zawiera informacje, których szukasz:

Deskryptor metody jest prawidłowy tylko wtedy, gdy reprezentuje parametry metody o łącznej długości 255 lub mniej, gdzie ta długość obejmuje udział w tym w przypadku wywołań metod instancji lub interfejsu. Całkowita długość jest obliczana poprzez zsumowanie wkładów poszczególnych parametrów, gdzie parametr typu long lub double dodaje dwie jednostki do długości, a parametr dowolnego innego typu - jedną jednostkę .

Dlatego wydaje się, że to, czy maszyna hosta jest 32-bitowa, czy 64-bitowa, nie ma wpływu na liczbę parametrów. Jeśli zauważysz, dokumentacja mówi w kategoriach „jednostek”, gdzie długość jednej „jednostki” jest funkcją rozmiaru słowa. Gdyby liczba parametrów była wprost proporcjonalna do rozmiaru słowa, wystąpiłyby problemy z przenoszeniem; nie byłbyś w stanie skompilować tego samego programu Java na różnych architekturach (zakładając, że przynajmniej jedna metoda wykorzystywała maksymalną liczbę parametrów w architekturze z większym rozmiarem słowa).

Vivin Paliath
źródło
10

Znalazłem interesujący numer z biuletynu na ten temat, http://www.javaspecialists.eu/archive/Issue059.html

Pula stałych dla poszczególnych klas lub interfejsów jest ograniczona do 65535 wpisów przez 16-bitowe pole constant_pool_count struktury ClassFile. Działa to jako wewnętrzne ograniczenie całkowitej złożoności pojedynczej klasy lub interfejsu. Ilość kodu na obcą, nieabstrakcyjną metodę jest ograniczona do 65536 bajtów przez rozmiary indeksów w tabeli wyjątków atrybutu Code, atrybucie LineNumberTable i atrybucie LocalVariableTable.

Największa liczba zmiennych lokalnych w tablicy zmiennych lokalnych ramki utworzonej po wywołaniu metody jest ograniczona do 65535 przez wielkość pozycji max_locals atrybutu Code podającego kod metody. Zauważ, że wartości typu long i double są uważane za rezerwujące dwie zmienne lokalne i wnoszą dwie jednostki do wartości max_locals, więc użycie zmiennych lokalnych tych typów dodatkowo ogranicza ten limit.

Liczba pól, które mogą być zadeklarowane przez klasę lub interfejs, jest ograniczona do 65535 przez rozmiar elementu fields_count struktury ClassFile. Należy zauważyć, że wartość elementu fields_count struktury ClassFile nie obejmuje pól dziedziczonych z nadklas lub superinterfejsów.

Matthew Brzezinski
źródło