ข้อผิดพลาดในการคอมไพล์“ โค้ดใหญ่เกินไป” ใน Java


94

มีขนาดสูงสุดสำหรับโค้ดใน Java หรือไม่? ฉันเขียนฟังก์ชันที่มีมากกว่า 10,000 บรรทัด จริงๆแล้วแต่ละบรรทัดจะกำหนดค่าให้กับตัวแปรอาร์เรย์

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"; 

และในขณะที่รวบรวมฉันได้รับข้อผิดพลาดนี้: รหัสมีขนาดใหญ่เกินไป

ฉันจะเอาชนะสิ่งนี้ได้อย่างไร


9
ฉันอึ้งไปเลย ... ต้องมีวิธีที่ดีกว่านี้
Thanos Papathanasiou

7
คุณต้องดูฐานข้อมูลสำหรับสิ่งประเภทนี้จริงๆโดยที่ไฟล์คุณสมบัตินั้นล้มเหลว
Paul Whelan

45
ทำไมพวกคุณถึงตะโกนใส่ผู้ชายที่น่าสงสารว่าออกแบบไม่ดี? บางที OP อาจได้รับวิธีบ้าๆนั้นโดยเครื่องมือสร้างโค้ด
webuster

15
ฉันตะลึงที่ความคิดเห็นเชิงวิจารณ์ตื้น ๆ เหล่านี้ได้รับการโหวตเพิ่มขึ้นมากมาย!
Evgeni Sergeev

7
เหตุใดการเริ่มต้นแอปพลิเคชันของคุณจึงใช้เวลามากในการแยกวิเคราะห์ไฟล์ข้อความเมื่อคุณสามารถให้คอมไพเลอร์สร้างทุกอย่างล่วงหน้าในเวลาคอมไพล์ได้ นี่เป็นการออกแบบที่ไม่ดีหากคุณต้องการเปลี่ยนข้อมูลโดยไม่ต้องคอมไพล์ใหม่หรือเขียนวิธีการด้วยตนเอง แต่ก็ไม่ใช่การออกแบบที่ไม่ดีเลยหากคุณสร้างซอร์สโค้ด (อย่างน้อยถ้าคุณทำในลักษณะที่อนุญาตให้คอมไพเลอร์สร้างอาร์เรย์ล่วงหน้า)
Guntram Blohm

คำตอบ:


93

เมธอดเดียวในคลาส Java อาจมีขนาดไม่เกิน 64KB ของ bytecode

แต่คุณควรทำความสะอาด!

ใช้.propertiesไฟล์เพื่อจัดเก็บข้อมูลนี้และโหลดผ่านไฟล์java.util.Properties

คุณสามารถทำได้โดยวาง.propertiesไฟล์บน classpath ของคุณและใช้:

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

2
"ไม่ว่าขนาดจริงสำหรับ JDK / JVM ของคุณจะเป็นเท่าไหร่"? คุณกำลังหมายความว่าขีด จำกัด นี้ไม่ได้รับการแก้ไขหรือไม่? เนื่องจากได้รับการแก้ไขและจำเป็นโดยข้อกำหนดรูปแบบไฟล์คลาส
Joachim Sauer

1
ฉันจะหาไฟล์. คุณสมบัติได้ที่ไหน
trinity

1
คุณสร้างของคุณเองแล้ววางไว้บน classpath
ทำเครื่องหมาย

3
ฉันไม่ได้ใช้คำแนะนำของคุณแม้ว่าฉันอยากจะลองในครั้งต่อไป .. ตอนนี้ได้ใช้ฐานข้อมูลเพื่อจัดเก็บข้อมูลนี้แล้วและ 'ได้แก้ไขโค้ดส่วนที่เหลือตามนั้น ..
trinity

1
ขอโทษด้วยถ้าเป็นคำถามโง่ ๆ แต่ .. ไฟล์. คุณสมบัตินี้ควรวางไว้ที่ไหน? ฉันหมายความว่าตกลงมันอยู่ใน classpath แต่มันอยู่ที่ไหน
Milack27

14

มีขีด จำกัด ขนาดรหัส 64K ไบต์สำหรับวิธีการ

ต้องบอกว่าฉันต้องเห็นด้วยกับ Richard; ทำไมคุณถึงต้องการวิธีที่ใหญ่ขนาดนั้น? จากตัวอย่างใน OP ไฟล์คุณสมบัติควรเพียงพอ ... หรือแม้แต่ฐานข้อมูลหากจำเป็น


4
แล้ว enums ล่ะ? ฉันได้รับปัญหาเดียวกันกับ enums ชุดใหญ่
Toby

1
@Toby: ไม่เคยเผชิญกับปัญหานี้ด้วยตัวเอง มีโพสต์โดยผู้ใช้รายอื่นที่นี่เกี่ยวกับปัญหาเดียวกันแม้ว่า ตัวอย่างเช่น - stackoverflow.com/questions/2546470อาจคุ้มค่าที่จะดูไฟล์. class ที่สร้างขึ้นenumเพื่อดู
ทุกคนใน

อินสแตนซ์ Enum (เช่นอ็อบเจ็กต์ที่แสดงค่าคงที่) ถูกสร้างขึ้นในตัวเริ่มต้นแบบคงที่ของคลาสซึ่งเป็นวิธีการและมีข้อ จำกัด เหมือนกัน
juancn

ฉันประสบปัญหาเดียวกันกับโค้ดที่สร้างกรอบสำหรับเว็บฟอร์มที่ซับซ้อนมาก วิธีแก้ปัญหาคือการแบ่งแบบฟอร์มในส่วนประกอบดังนั้นรหัสที่สร้างขึ้นสำหรับแต่ละองค์ประกอบจึงถูกแบ่งออกด้วย
SebaGra

13

ตามที่Java เปคเครื่องเสมือน , รหัสของวิธีการที่จะต้องไม่ใหญ่กว่า 65536 ไบต์ :

ค่าของcode_lengthรายการให้จำนวนไบต์ในcodeอาร์เรย์สำหรับวิธีนี้

ค่าของ code_length ต้องมากกว่าศูนย์ (เนื่องจากโค้ดอาร์เรย์ต้องไม่ว่างเปล่า) และน้อยกว่า 65536

code_lengthกำหนดขนาดของcode[]แอตทริบิวต์ซึ่งมี bytecode จริงของวิธีการ:

codeอาร์เรย์ให้ไบต์ที่แท้จริงของ Java รหัสเครื่องเสมือนที่ใช้วิธีการ


7

นี่ดูเหมือนความบ้าคลั่ง คุณไม่สามารถเริ่มต้นอาร์เรย์โดยการอ่านค่าจากไฟล์ข้อความหรือแหล่งข้อมูลอื่น ๆ ได้หรือไม่?


3
(โหวตลงเพราะ) สิ่งนี้ต้องการเหตุผลอย่างน้อยหนึ่งข้อว่าทำไมเทคนิคดังกล่าวถึงไม่ดี ไม่ใช่เรื่องง่ายที่จะหาเหตุผลที่ดี
Evgeni Sergeev

3

บางครั้งข้อผิดพลาดนี้เกิดขึ้นเนื่องจากรหัสใหญ่เกินไปในฟังก์ชันเดียว ... ในการแก้ไขข้อผิดพลาดนั้นให้แยกฟังก์ชันนั้นออกเป็นหลายฟังก์ชันเช่น

//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();
}

2

ลองเปลี่ยนรหัสของคุณใหม่ มีข้อ จำกัด เกี่ยวกับขนาดของวิธีการใน Java


1
การปรับโครงสร้างใหม่ไม่ได้เป็นความคิดที่สมเหตุสมผลหากสิ่งที่เขาทำในวิธีนั้นคือการเริ่มต้นอาร์เรย์
Gabriel Ščerbák

2
เขาบอกว่าโค้ดที่เหลือขึ้นอยู่กับว่านี่คืออาร์เรย์ ดังนั้นเขาจึงสามารถ refactor วิธีการเพื่อส่งต่อความรับผิดชอบในการโหลดข้อมูลไปยังวิธีการอื่น / โรงงานจากไฟล์ / ฐานข้อมูล
Padmarag

คุณสามารถสร้างและเริ่มต้นอาร์เรย์ขนาดใหญ่โดยไม่ต้องใช้เรื่องไร้สาระประเภทนี้ ดูคำตอบของ @ Kris
Stephen C

Refactor - "ขั้นตอนการเปลี่ยนซอร์สโค้ดของโปรแกรมคอมพิวเตอร์โดยไม่แก้ไขลักษณะการทำงานภายนอกเพื่อปรับปรุงคุณลักษณะบางอย่างที่ไม่สามารถใช้งานได้ของซอฟต์แวร์" คำตอบอื่น ๆ แตกต่างจากนี้อย่างไร?
Padmarag

2

ตามที่กล่าวไว้ในคำตอบอื่น ๆ มีขีด จำกัด bytecode 64KB สำหรับวิธีการ (อย่างน้อยในคอมไพเลอร์ java ของ Sun)

เช่นกันฉันควรแบ่งวิธีการนั้นออกเป็นวิธีการอื่น ๆ - แต่ละคนจะกำหนดสิ่งที่เกี่ยวข้องบางอย่างให้กับอาร์เรย์ (อาจเหมาะสมกว่าที่จะใช้ ArrayList เพื่อทำสิ่งนี้)

ตัวอย่างเช่น:

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

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

หรือคุณสามารถโหลดรายการจากทรัพยากรแบบคงที่หากได้รับการแก้ไขเช่นจากไฟล์คุณสมบัติ


คำตอบที่ถูกต้องคือการถือว่าข้อมูลเป็นข้อมูลและรหัสเป็นรหัส
Malcolm

@ มัลคอล์มนี่เป็นข้อมูลที่ชัดเจนไม่ใช่รหัส ความคิดเห็นของคุณทำให้เข้าใจผิดเพราะสิ่งที่คุณไม่ควรทำคือผสมข้อมูลและโค้ด แต่จะไม่ผสมกัน
Evgeni Sergeev

ฉันคิดว่านี่เป็นวิธีที่ดีฉันเจอปัญหานี้ด้วยรหัสประมาณ 21k บรรทัดพร้อมข้อความเส้นทาง 7000 ข้อความฉันแก้ไขโดยแบ่งข้อความเส้นทางเหล่านั้นออกเป็น 7 ฟังก์ชันด้วยชื่อ xxx0 xxx1 xxx2
บรอนซ์แมน

2

ฉันพบปัญหานี้ด้วยตัวเอง วิธีแก้ปัญหาที่ได้ผลสำหรับฉันคือการปรับโครงสร้างใหม่และลดขนาดวิธีการให้เป็นชิ้นส่วนที่จัดการได้มากขึ้น เช่นเดียวกับคุณฉันกำลังจัดการกับวิธีการเส้นเกือบ 10,000 อย่างไรก็ตามด้วยการใช้ตัวแปรคงที่และฟังก์ชันโมดูลาร์ที่มีขนาดเล็กปัญหาก็จะได้รับการแก้ไข

ดูเหมือนจะมีวิธีแก้ปัญหาที่ดีกว่า แต่การใช้ Java 8 ไม่มีเลย ...


1

คุณสามารถเพิ่มวิธีอื่นเพื่อสร้างพื้นที่สำหรับโค้ดของคุณสำหรับพื้นที่ข้อมูลเพิ่มเติมคุณอาจมีวิธีการที่ใช้พื้นที่ข้อมูลจำนวนมาก ลองแบ่งวิธีการของคุณเพราะฉันมีปัญหาเดียวกันและแก้ไขโดยสร้างวิธีอื่นเพิ่มเติมสำหรับข้อมูลเดียวกันในโค้ด java Android ของฉันปัญหาก็หายไปหลังจากที่ฉันทำเช่นนั้น


นี่เป็นความคิดเห็นมากกว่าคำตอบ
user3071284

0

ฉันมี enum ที่ทำให้ไฟล์. java มีขนาดเกิน 500KB Eclipse สามารถสร้างได้ด้วยเหตุผลบางประการ ant build.xml ที่ส่งออก eclipse ไม่สามารถ ฉันกำลังตรวจสอบสิ่งนี้และจะอัปเดตโพสต์นี้


0

เนื่องจากมีการ จำกัด ขนาดสำหรับวิธีการและคุณไม่ต้องการออกแบบโค้ดของคุณใหม่ในขณะนี้คุณสามารถแบ่งอาร์เรย์ออกเป็น 4-5 ส่วนจากนั้นใส่ลงในวิธีการต่างๆ ในขณะอ่านอาร์เรย์ให้เรียกใช้เมธอดทั้งหมดในอนุกรม คุณสามารถรักษาตัวนับได้เช่นกันเพื่อให้ทราบว่าคุณได้แยกวิเคราะห์ดัชนีไปแล้วกี่ดัชนี


0

นี่เป็นเพราะโค้ดทั้งหมดในโซลูชันวิธีเดียว: สร้างวิธีการเล็ก ๆ เพิ่มเติมจากนั้นข้อผิดพลาดนี้จะหายไป


0

โอเคบางทีคำตอบนี้อาจจะสายเกินไป แต่ฉันคิดว่าวิธีนี้ดีกว่าวิธีอื่น

ตัวอย่างเช่นเรามีข้อมูล 1,000 แถวในโค้ด

  1. ทำลายพวกเขา

    private void rows500() {
         //you shoud write 1-500 rows here
    }
    
    private void rows1000() {
         you shoud write 500-1000 rows here
    }
    
  2. เพื่อประสิทธิภาพที่ดีขึ้นให้ใส่ "if" ในรหัสของคุณ

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

ฉันหวังว่ารหัสนี้จะช่วยคุณได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.