Lỗi biên dịch "Mã quá lớn" trong Java


94

Có kích thước tối đa nào cho mã trong Java không? Tôi đã viết một hàm với hơn 10.000 dòng. Trên thực tế, mỗi dòng gán một giá trị cho một biến mảng.

arts_bag[10792]="newyorkartworld";
arts_bag[10793]="leningradschool";
arts_bag[10794]="mailart";
arts_bag[10795]="artspan";
arts_bag[10796]="watercolor";
arts_bag[10797]="sculptures";
arts_bag[10798]="stonesculpture"; 

Và trong khi biên dịch, tôi gặp lỗi này: mã quá lớn

Làm thế nào để tôi vượt qua điều này?


9
Tôi chỉ thấy choáng váng ... Nhất định phải có cách tốt hơn để làm điều này.
Thanos Papathanasiou

6
Bạn thực sự cần phải xem xét một cơ sở dữ liệu cho loại điều này, đó là một tệp thuộc tính.
Paul Whelan

44
Tại sao các bạn lại la mắng anh chàng nghèo vì thiết kế xấu? Có thể OP đã lấy được phương pháp điên rồ đó bằng một công cụ tạo mã nào đó.
webuster

14
Tôi rất ngạc nhiên khi những bình luận chỉ trích nông cạn này lại nhận được rất nhiều lượt ủng hộ!
Evgeni Sergeev

7
Tại sao việc khởi động ứng dụng của bạn lại mất nhiều thời gian bằng cách phân tích cú pháp một số tệp văn bản trong khi bạn có thể để trình biên dịch tạo trước mọi thứ tại thời điểm biên dịch? Đây là thiết kế tồi nếu bạn muốn thay đổi dữ liệu mà không cần biên dịch lại hoặc viết phương thức theo cách thủ công, nhưng nó không phải là thiết kế tồi nếu bạn tạo mã nguồn. (Ít nhất nếu bạn thực hiện theo cách thực sự cho phép trình biên dịch tạo trước mảng).
Guntram Blohm ủng hộ Monica.

Câu trả lời:


92

Một phương thức duy nhất trong một lớp Java có thể có tối đa 64KB bytecode.

Nhưng bạn nên làm sạch điều này!

Sử dụng .propertiestệp để lưu trữ dữ liệu này và tải nó quajava.util.Properties

Bạn có thể thực hiện việc này bằng cách đặt .propertiestệp trên classpath của mình và sử dụng:

Properties properties = new Properties();
InputStream inputStream = getClass().getResourceAsStream("yourfile.properties");
properties.load(inputStream);

2
"Bất kể kích thước thực tế cho JDK / JVM của bạn là bao nhiêu"? Bạn đang ngụ ý rằng giới hạn này không cố định? Bởi vì nó được cố định và yêu cầu bởi đặc tả định dạng tệp lớp.
Joachim Sauer

1
nơi mà tôi có thể tìm thấy các tập tin .properties
trinity

1
bạn tạo của riêng bạn sau đó đặt nó trên classpath
Đánh dấu

3
i didnt sử dụng gợi ý của bạn, mặc dù tôi đang háo hức để thử nó lần sau .. bây giờ đã sử dụng một cơ sở dữ liệu để lưu trữ thông tin này, và 'đã được sửa đổi phần còn lại của các mã tương ứng ..
trinity

1
Tôi xin lỗi nếu đây là một câu hỏi ngu ngốc, nhưng .. Tệp .properties này nên được đặt ở đâu? Ý tôi là, ok, nó nằm trong classpath, nhưng nó ở đâu?
Milack27

14

Có giới hạn kích thước mã byte 64K trên một phương thức

Đã nói rằng, tôi phải đồng ý với Richard; tại sao bạn cần một phương pháp lớn như vậy? Với ví dụ trong OP, một tệp thuộc tính phải đủ ... hoặc thậm chí là cơ sở dữ liệu nếu được yêu cầu.


4
làm thế nào về enums? tôi gặp vấn đề tương tự với bộ enum lớn
Toby

1
@Toby: Bản thân tôi chưa từng đối mặt với vấn đề này với enum. Có những bài đăng của những người dùng khác ở đây trên SO về cùng một vấn đề. Ví dụ - stackoverflow.com/questions/2546470 Có thể đáng giá khi xem tệp .class đã tạo enumđể xem
Mọi người

Các cá thể enum (tức là các đối tượng đại diện cho các hằng số) được tạo trong trình khởi tạo tĩnh của lớp, là một phương thức và có cùng một giới hạn.
juancn

Tôi phải đối mặt với vấn đề tương tự với mã do khuôn khổ tạo cho một biểu mẫu web thực sự phức tạp. Giải pháp là chia biểu mẫu thành các thành phần, vì vậy mã được tạo cho từng thành phần cũng được chia nhỏ.
SebaGra

12

Theo đặc tả Máy ảo Java , mã của một phương thức không được lớn hơn 65536 byte :

Giá trị của code_lengthmục cung cấp số byte trong codemảng cho phương thức này.

Giá trị của code_length phải lớn hơn 0 (vì mảng mã không được để trống) và nhỏ hơn 65536.

code_lengthxác định kích thước của code[]thuộc tính có chứa mã bytecode thực của một phương thức:

Các codemảng cung cấp cho các byte thực tế của mã Java Virtual Machine mà thực hiện phương pháp này.


7

Điều này có vẻ hơi giống như sự điên rồ. Bạn có thể không khởi tạo mảng bằng cách đọc các giá trị từ tệp văn bản hoặc một số nguồn dữ liệu khác không?


3
(Bị phản đối vì) Điều này cần ít nhất một lý do tại sao kỹ thuật như vậy lại tệ. Thật không dễ dàng để đưa ra một lý do chính đáng.
Evgeni Sergeev

2

Cố gắng cấu trúc lại mã của bạn. Có giới hạn về kích thước của phương thức trong Java.


1
refactoring không phải là một ý tưởng hợp lý nếu tất cả những gì anh ta làm trong phương thức đó là khởi tạo mảng.
Gabriel Ščerbák

2
Anh ấy nói rằng phần còn lại của mã của anh ấy phụ thuộc vào đây là một mảng. Vì vậy, anh ta có thể cấu trúc lại phương thức để chuyển trách nhiệm tải dữ liệu sang một số phương thức khác / Nhà máy từ tệp / cơ sở dữ liệu.
Padmarag

bạn có thể tạo và khởi tạo các mảng lớn mà không cần dùng đến loại vô nghĩa này; xem câu trả lời của @ Kris.
Stephen C

Refactor - "Quy trình thay đổi mã nguồn của chương trình máy tính mà không sửa đổi hành vi chức năng bên ngoài của nó để cải thiện một số thuộc tính phi chức năng của phần mềm." Câu trả lời khác khác với câu trả lời này như thế nào?
Padmarag

2

Như đã đề cập trong các câu trả lời khác, có giới hạn 64KB bytecode cho một phương thức (ít nhất là trong trình biên dịch java của Sun)

Tôi cũng vậy, sẽ hợp lý hơn nếu chia nhỏ phương thức đó thành nhiều phương thức hơn - mỗi phương thức gán một số nội dung liên quan nhất định cho mảng (có thể hợp lý hơn khi sử dụng ArrayList để thực hiện điều này)

ví dụ:

public void addArrayItems()
{
  addSculptureItems(list);
  ...
}

public void addSculptureItems(ArrayList list)
{
  list.add("sculptures");
  list.add("stonesculpture");
}

Ngoài ra, bạn có thể tải các mục từ tài nguyên tĩnh nếu chúng được sửa như từ tệp thuộc tính


Đáp án đúng là coi dữ liệu là dữ liệu và mã là mã.
Malcolm

@Malcolm Chà, đây rõ ràng là dữ liệu chứ không phải mã. Nhận xét của bạn gây hiểu lầm, bởi vì điều bạn không nên làm là trộn dữ liệu và mã, nhưng ở đây chúng không bị trộn lẫn.
Evgeni Sergeev

Tôi nghĩ rằng đây là một công việc tốt. Tôi gặp vấn đề này với khoảng 21k dòng mã với 7000 thông báo định tuyến trong đó. Tôi sửa nó bằng cách chia các thông báo định tuyến đó thành 7 hàm với tên xxx0 xxx1 xxx2.
người đàn ông đồ đồng

2

Tôi đã gặp phải vấn đề này chính mình. Giải pháp phù hợp với tôi là tái cấu trúc và thu nhỏ phương pháp thành những phần dễ quản lý hơn. Giống như bạn, tôi đang đối phó với một phương pháp gần 10K dòng. Tuy nhiên, với việc sử dụng các biến tĩnh cũng như các hàm mô-đun nhỏ hơn, vấn đề đã được giải quyết.

Có vẻ như sẽ có một giải pháp tốt hơn, nhưng sử dụng Java 8, không có ...


2

Lỗi này đôi khi xảy ra do mã quá lớn trong một chức năng ... Để giải quyết lỗi đó, hãy chia chức năng đó thành nhiều chức năng, như

//Too large code function
private void mySingleFunction(){
.
.
2000 lines of code
}
//To solve the problem
private void mySingleFunction_1(){
.
.
500 lines of code
}
private void mySingleFunction_2(){
.
.
500 lines of code
}
private void mySingleFunction_3(){
.
.
500 lines of code
}
private void mySingleFunction_4(){
.
.
500 lines of code
}
private void MySingleFunction(){
mySingleFunction_1();
mySingleFunction_2();
mySingleFunction_3();
mySingleFunction_4();
}

1

Bạn có thể thêm một phương thức khác để tạo không gian cho mã của mình để có thêm không gian dữ liệu, bạn có thể có một phương thức đang chiếm một lượng lớn không gian dữ liệu. Hãy thử phân chia các phương pháp của bạn vì tôi đã gặp sự cố tương tự và khắc phục nó bằng cách tạo một phương pháp bổ sung khác cho cùng một dữ liệu trong mã java Android của tôi, Sự cố đã biến mất sau khi tôi thực hiện điều đó.


Đây là một bình luận hơn là một câu trả lời.
user3071284 23/12/15

0

Tôi có một enum khiến tệp .java có kích thước hơn 500KB. Eclipse có thể xây dựng nó vì một số lý do; kiến build.xml được xuất nhật thực không thể. Tôi đang xem xét điều này và sẽ cập nhật bài đăng này.


0

Vì có giới hạn kích thước cho các phương thức và bạn không muốn thiết kế lại mã của mình vào thời điểm này, có thể bạn có thể chia mảng thành 4-5 phần và sau đó đặt chúng thành các phương thức khác nhau. Tại thời điểm đọc mảng, hãy gọi tất cả các phương thức trong một chuỗi. Bạn cũng có thể duy trì một bộ đếm để biết bạn đã phân tích cú pháp bao nhiêu chỉ mục.


0

điều này là do tất cả mã trong giải pháp phương pháp đơn: tạo thêm một số phương thức nhỏ thì lỗi này sẽ biến mất


0

ok có lẽ câu trả lời này là quá muộn nhưng tôi nghĩ cách này tốt hơn cách khác nên

ví dụ: chúng tôi có dữ liệu 1000 hàng trong mã

  1. phá vỡ chúng

    private void rows500() {
         //you shoud write 1-500 rows here
    }
    
    private void rows1000() {
         you shoud write 500-1000 rows here
    }
  2. để có hiệu suất tốt hơn, hãy đặt "nếu" trong mã của bạn

    if (count < 500) {
        rows500();
    } else if (count > 500) {
        rows1000();
    }

Tôi hy vọng mã này sẽ giúp bạ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.