Số lượng tham số tối đa trong khai báo phương thức Java


133

Số lượng tham số tối đa mà một phương thức trong Java có thể có là gì và tại sao?

Tôi đang sử dụng Java 1.8 trên hệ thống Windows 64 bit.

Tất cả các câu trả lời trên StackOverflow về điều này nói rằng giới hạn kỹ thuật là 255 tham số mà không chỉ định lý do tại sao.

Nói chính xác, 255 cho tĩnh và 254 cho các phương thức không tĩnh ( thissẽ là thứ 255 trong trường hợp này).

Tôi nghĩ rằng điều này có thể được mô tả trong một số loại đặc tả và chỉ đơn giản là có một số lượng tham số tối đa được xác định tĩnh cho phép.

Nhưng điều này chỉ hợp lệ cho intvà tất cả các loại 4 byte . Tôi đã thực hiện một số thử nghiệm với longcác tham số và tôi chỉ có thể khai báo 127 tham số trong trường hợp đó.

Với Stringcác tham số, số lượng được phép tôi suy ra từ thử nghiệm là 255 (có thể là do kích thước tham chiếu là 4 byte trong Java?).

Nhưng vì tôi đang sử dụng hệ thống 64 bit, kích thước tham chiếu phải rộng 8 byte và do đó, với Stringcác tham số, số lượng tối đa được phép phải là 127, tương tự như các longloại.

Làm thế nào để giới hạn này được áp dụng chính xác?

Liệu giới hạn có liên quan gì đến kích thước ngăn xếp của phương thức không?

Lưu ý: Tôi không thực sự sẽ sử dụng nhiều tham số này trong bất kỳ phương thức nào, nhưng câu hỏi này chỉ để làm rõ hành vi chính xác.


39
7, nếu bạn không muốn phát điên với khả năng đọc. (Tôi biết những gì bạn đang thực sự hỏi).
Adam

14
Tôi sẽ tranh luận <= 4. Bất cứ điều gì nhiều hơn có lẽ nên được gói vào một đối tượng.
Vivin Paliath

4
Tại sao đây là một câu hỏi thú vị? Nếu bạn đang viết một chương trình và bạn đang đạt đến giới hạn này, thì thiết kế của bạn đã sai. Tôi không hiểu tại sao một câu hỏi thực tế vô dụng lại nhận được nhiều sự ủng hộ như vậy.
Jesper

20
@Jesper vì câu hỏi này kiến ​​thức về đặc tả JVM. Câu hỏi này không hỏi "Làm thế nào để làm điều này hay điều đó?" thay vào đó, nó đặt câu hỏi "Tại sao tôi cần điều đó?" ... +1 Câu hỏi thú vị Userv
Amit

2
@amit chính xác những gì tôi đã nghĩ. OP chỉ tò mò về nó.
Evan Carslake

Câu trả lời:


110

Giới hạn đó được định nghĩa trong Đặc tả JVM :

Số lượng tham số phương thức được giới hạn ở 255 theo định nghĩa của bộ mô tả phương thức (§4.3.3), trong đó giới hạn bao gồm một đơn vị cho điều này trong trường hợp yêu cầu phương thức giao diện hoặc ví dụ.

Phần §4.3.3 cung cấp một số thông tin bổ sung:

Bộ mô tả phương thức chỉ hợp lệ nếu nó đại diện cho các tham số phương thức có tổng độ dài từ 255 trở xuống, trong đó độ dài đó bao gồm phần đóng góp cho điều này trong trường hợp các yêu cầu phương thức giao diện hoặc ví dụ.

Tổng chiều dài được tính bằng cách tính tổng các đóng góp của các tham số riêng lẻ, trong đó một tham số loại dài hoặc gấp đôi đóng góp hai đơn vị cho chiều dài và tham số của bất kỳ loại nào khác đóng góp một đơn vị .

Các quan sát của bạn đã được phát hiện, các từ nguyên thủy kép ( long/ double) cần gấp đôi kích thước của các biến 4 byte thông thường và các tham chiếu đối tượng 4 byte .

Về phần cuối cùng của câu hỏi của bạn liên quan đến các hệ thống 64 bit, đặc tả xác định có bao nhiêu đơn vị tham số đóng góp , phần đó của thông số kỹ thuật vẫn phải được tuân thủ ngay cả trên nền tảng 64 bit, JVM 64 bit sẽ chứa 255 tham số (như 255 của bạn Strings) bất kể kích thước con trỏ của đối tượng nội bộ.


10
Tôi muốn thêm vào câu trả lời này rằng trên kiến ​​trúc 64 bit, ngăn xếp cũng là 64 bit. Vì vậy, do giới hạn về số lượng tham số bị ràng buộc kích thước ngăn xếp, ngăn xếp 64 bit cho phép lưu trữ cùng 255 tham chiếu đối tượng. Việc xử lý cụ thể longdoublebất kể kiến ​​trúc hệ thống xảy ra ở nhiều nơi của thông số kỹ thuật và dường như là tàn dư của kỷ nguyên 32 bit.
Sergei

Tôi đang trong quá trình chỉnh sửa phần đó :) Đồng ý, thông số kỹ thuật vẫn phải được tôn trọng ngay cả trên các nền tảng khác nhau.
Umberto Raimondi

1
Vâng, nếu số lượng tham số là một hàm của kích thước từ, thì điều đó sẽ phá vỡ tính di động; bạn không thể biên dịch cùng một chương trình Java trên các kiến ​​trúc khác nhau.
Vivin Paliath

3
Các biến được biến thành một mảng Object , chỉ có thể được sử dụng một lần trong danh sách tham số và chiếm vị trí cuối cùng. Xem xét tất cả những điều này, tôi muốn nói rằng bằng cách sử dụng varargs, số lượng tham số có thể được "mở rộng" thành 254 + Integer.MAX_VALUE (ít nhất là đối với lập trình viên ... tham số vẫn là 255), vì vậy sử dụng thủ thuật đó bạn có thể có Integer. Tham số đối tượng MAX_VALUE.
Umberto Raimondi

1
@MrTsjolder Hãy xem câu trả lời này cho varargs.
Vivin Paliath

11

Mục 4.3.3 của đặc tả JVM có thông tin bạn đang tìm kiếm:

Một bộ mô tả phương thức chỉ hợp lệ nếu nó đại diện cho các tham số phương thức có tổng độ dài từ 255 trở xuống, trong đó độ dài đó bao gồm phần đóng góp cho điều này trong trường hợp các yêu cầu phương thức giao diện hoặc ví dụ. Tổng chiều dài được tính bằng cách tính tổng các đóng góp của các tham số riêng lẻ, trong đó một tham số loại dài hoặc gấp đôi đóng góp hai đơn vị cho chiều dài và tham số của bất kỳ loại nào khác đóng góp một đơn vị .

Do đó, có vẻ như máy chủ là 32 bit hay 64 bit không ảnh hưởng đến số lượng tham số. Nếu bạn chú ý, tài liệu nói về "đơn vị", trong đó độ dài của một "đơn vị" là một chức năng của kích thước từ. Nếu số lượng tham số tỷ lệ thuận với kích thước từ, sẽ có vấn đề về tính di động; bạn sẽ không thể biên dịch cùng một chương trình Java trên các kiến ​​trúc khác nhau (giả sử rằng ít nhất một phương thức đã sử dụng số lượng tham số tối đa trên kiến ​​trúc với kích thước từ lớn hơn).


10

Tôi đã tìm thấy một vấn đề thú vị từ một bản tin về điều này, http://www.javaspecialists.eu/archive/Issue059.html

Nhóm hằng số trên mỗi lớp hoặc trên mỗi giao diện được giới hạn ở 65535 mục nhập bởi trường hằng số 16 bit của cấu trúc ClassFile. Điều này hoạt động như một giới hạn nội bộ trên tổng độ phức tạp của một lớp hoặc giao diện. Số lượng mã cho mỗi phương thức không bản địa, không trừu tượng được giới hạn ở 65536 byte theo kích thước của các chỉ mục trong ngoại lệ_table của thuộc tính Code, trong thuộc tính LineNumberTable và trong thuộc tính LocalVariableTable.

Số lượng biến cục bộ lớn nhất trong mảng biến cục bộ của khung được tạo khi gọi phương thức được giới hạn ở 65535 bởi kích thước của mục max_locals của thuộc tính Code cung cấp mã của phương thức. Lưu ý rằng các giá trị của loại dài và gấp đôi được xem xét để dự trữ hai biến cục bộ và đóng góp hai đơn vị cho giá trị max_locals, vì vậy việc sử dụng biến cục bộ của các loại đó làm giảm thêm giới hạn này.

Số lượng các trường có thể được khai báo bởi một lớp hoặc giao diện được giới hạn ở 65535 bởi kích thước của mục Field_count của cấu trúc ClassFile. Lưu ý rằng giá trị của mục Field_count của cấu trúc ClassFile không bao gồm các trường được kế thừa từ các siêu lớp hoặc siêu giao diện.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.