หน่วยความจำสูงสุดของ Java บน Windows XP


103

ฉันสามารถจัดสรร 1400 เมกะไบต์สำหรับ Java SE ที่ทำงานบน Windows XP แบบ 32 บิต (Java 1.4, 1.5 และ 1.6) ได้เสมอ

java -Xmx1400m ...

วันนี้ฉันลองใช้ตัวเลือกเดียวกันในเครื่อง Windows XP ใหม่โดยใช้ Java 1.5_16 และ 1.6.0_07 และได้รับข้อผิดพลาด:

Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

จากการลองผิดลองถูกดูเหมือนว่า 1200 เมกะไบต์เป็นสิ่งที่มากที่สุดที่ฉันสามารถจัดสรรได้บนเครื่องนี้

มีความคิดว่าทำไมเครื่องหนึ่งยอมให้ 1400 และอีกเครื่องเพียง 1200

แก้ไข: เครื่องมี RAM 4GB และประมาณ 3.5GB ที่ Windows รับรู้ได้


คุณจะสังเกตเห็นความแตกต่างในค่าสูงสุดระหว่างการรันแอปในเชลล์ 32 บิตหรือเชลล์ 64 บิตอย่างน้อยก็ในประสบการณ์ของฉันแม้ว่าระบบ WindowsXP 64 บิตจะหายาก
djangofan

คำตอบ:


124

โปรดทราบว่า Windows มีการจัดการหน่วยความจำเสมือนและ JVM ต้องการหน่วยความจำที่อยู่ติดกันในพื้นที่แอดเดรสเท่านั้น ดังนั้นโปรแกรมอื่น ๆ ที่ทำงานบนระบบไม่ควรส่งผลกระทบต่อขนาดฮีปของคุณเสมอไป สิ่งที่จะเข้ามาในทางของคุณคือ DLL ที่โหลดในพื้นที่ที่อยู่ของคุณ น่าเสียดายที่การเพิ่มประสิทธิภาพใน Windows ที่ลดการย้ายตำแหน่งของ DLL ในระหว่างการเชื่อมโยงทำให้มีโอกาสมากขึ้นที่คุณจะมีพื้นที่ที่อยู่ที่กระจัดกระจาย สิ่งที่มีแนวโน้มที่จะตัดพื้นที่ที่อยู่ของคุณนอกเหนือจากสิ่งปกติ ได้แก่ ซอฟต์แวร์ความปลอดภัยซอฟต์แวร์ CBT สปายแวร์และมัลแวร์รูปแบบอื่น ๆ สาเหตุที่เป็นไปได้ของความแปรปรวนคือแพตช์ความปลอดภัยที่แตกต่างกันเวอร์ชันรันไทม์ C ฯลฯ ไดรเวอร์อุปกรณ์และบิตเคอร์เนลอื่น ๆ มีพื้นที่แอดเดรสของตัวเอง (อีก 2GB ของพื้นที่ 4GB 32 บิต)

คุณสามารถลองใช้การเชื่อมโยง DLL ของคุณในกระบวนการ JVM ของคุณและดูที่การพยายามสร้างฐานข้อมูล DLL ของคุณใหม่เป็นพื้นที่ที่อยู่ที่กะทัดรัดยิ่งขึ้น ไม่สนุก แต่ถ้าหมดหวัง ...

หรือคุณสามารถเปลี่ยนไปใช้ Windows 64 บิตและ JVM 64 บิต แม้จะมีสิ่งที่คนอื่นมีข้อเสนอแนะในขณะที่มันจะเคี้ยว RAM มากขึ้นคุณจะมีมากพื้นที่ที่อยู่เสมือนที่อยู่ติดกันมากขึ้นและการจัดสรร 2GB ติดกันจะเป็นที่น่ารำคาญ


5
ใช้ Process Explorer เพื่อดูว่ากำลังโหลด dll ของหน่วยความจำที่ใด บ่อยครั้งที่ไดรเวอร์ที่อัปเดตบางตัวจะติดอยู่ตรงกลางช่องที่อยู่ของคุณ การใช้คำสั่ง REBASE คุณสามารถผลักดันสิ่งเหล่านี้ออกไปได้อย่างง่ายดาย อย่างไรก็ตามโปรดทราบว่า dll อาจได้รับการอัปเดตอีกครั้งและทำลายสิ่งต่างๆ
brianegge

@Christopher เป็นไปได้ไหมที่จะใช้ JVM 64 บิตบน Windows XP 32 บิต
Pacerier

@Pacerier ขออภัยฉันพลาดคำถามของคุณ AFAIK มันเป็นไปไม่ได้ OS X มีเทคนิคบางอย่างสำหรับพื้นที่ผู้ใช้ 64 บิตพร้อมเคอร์เนล 32 บิต แต่ฉันไม่เคยได้ยินเรื่องนี้สำหรับ Windows
Christopher Smith

@ChristopherSmith คุณพูดถึง " โปรแกรมอื่น ๆ ที่ทำงานบนระบบไม่ควรส่งผลกระทบต่อขนาดฮีปของคุณ " ถ้าเป็นเช่นนั้นเราจะอธิบายผลลัพธ์นี้อย่างไร: stackoverflow.com/questions/9303889/… ?
Pacerier

@brianegge คุณใช้ process explorer เพื่อดู dll ที่โหลดได้อย่างไร?
speedplane

50

สิ่งนี้เกี่ยวข้องกับหน่วยความจำที่ต่อเนื่องกัน

นี่คือข้อมูลบางส่วนที่พบทางออนไลน์สำหรับบางคนที่ถามก่อนหน้านี้ซึ่งคาดว่ามาจาก "VM god":

เหตุผลที่เราต้องการพื้นที่หน่วยความจำที่ต่อเนื่องกันสำหรับฮีปคือเรามีโครงสร้างข้อมูลด้านข้างจำนวนมากซึ่งจัดทำดัชนีโดย (ปรับขนาด) ออฟเซ็ตตั้งแต่เริ่มต้นของฮีป ตัวอย่างเช่นเราติดตามการอัปเดตการอ้างอิงออบเจ็กต์ด้วย "การ์ดเครื่องหมายอาร์เรย์" ที่มีหนึ่งไบต์สำหรับแต่ละฮีป 512 ไบต์ เมื่อเราจัดเก็บข้อมูลอ้างอิงในฮีปเราต้องทำเครื่องหมายไบต์ที่เกี่ยวข้องในอาร์เรย์เครื่องหมายการ์ด เราเปลี่ยนที่อยู่ปลายทางของร้านค้าอย่างถูกต้องและใช้ที่อยู่เพื่อจัดทำดัชนีอาร์เรย์เครื่องหมายการ์ด สนุกกับเกมเลขคณิตที่คุณไม่สามารถทำได้ใน Java ที่คุณทำได้ (ต้อง :-) เล่นใน C ++

โดยปกติแล้วเราไม่มีปัญหาในการรับพื้นที่ที่อยู่ติดกันเล็กน้อย (สูงสุดประมาณ 1.5GB บน Windohs สูงสุดประมาณ 3.8GB บน Solaris YMMV) ใน Windohs ปัญหาส่วนใหญ่คือมีบางไลบรารีที่โหลดก่อนที่ JVM จะเริ่มทำงานซึ่งจะแบ่งพื้นที่ที่อยู่ออก การใช้สวิตช์ / 3GB จะไม่สร้างฐานไลบรารีเหล่านั้นใหม่ดังนั้นจึงยังคงเป็นปัญหาสำหรับเรา

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


ที่น่าสนใจมาก. ฉันถามตัวเองเสมอว่าทำไมถึง 1500 MB ตอนนี้ฉันได้มาแล้วขอบคุณ!
Tim Büthe

3
ขออภัยที่ติดตามคำถามเก่า ๆ แต่นี่เป็นคำตอบที่ดีที่สุดที่ฉันเคยเห็นจนถึงตอนนี้ แต่เหตุใด JVM จึงล้มเหลวเมื่อเริ่มต้นหากไม่สามารถรับขนาดฮีปสูงสุดได้ มันควรจะเงียบเพื่อให้ได้ขนาดที่ดีที่สุดที่สูงกว่าขั้นต่ำหรือไม่?
Stroboskop

19

ขีด จำกัด ขนาดฮีป Java สำหรับ Windows คือ:

  • ขนาดฮีปสูงสุดที่เป็นไปได้บน Java 32 บิต: 1.8 GB
  • ขีด จำกัด ขนาดฮีปที่แนะนำบน Java 32 บิต: 1.5 GB (หรือ1.8 GBพร้อมตัวเลือก / 3GB)

สิ่งนี้ไม่ได้ช่วยให้คุณได้รับ Java heap ที่ใหญ่ขึ้น แต่ตอนนี้คุณรู้แล้วว่าคุณไม่สามารถก้าวข้ามค่าเหล่านี้ไปได้


10

Oracle JRockitซึ่งสามารถจัดการฮีปที่ไม่ต่อเนื่องกันสามารถมีขนาดฮีป Java 2.85 GB บน Windows 2003 / XP พร้อมสวิตช์ / 3GB ดูเหมือนว่าการแยกส่วนสามารถส่งผลกระทบค่อนข้างมากต่อความใหญ่ของ Java heap


6

JVM ต้องการหน่วยความจำที่ต่อเนื่องกันและขึ้นอยู่กับสิ่งที่กำลังทำงานอยู่สิ่งที่กำลังทำงานอยู่ก่อนหน้านี้และวิธีที่ Windows จัดการหน่วยความจำคุณอาจได้รับหน่วยความจำที่ต่อเนื่องกันมากถึง 1.4GB ฉันคิดว่า Windows 64 บิตจะอนุญาตให้มีฮีปขนาดใหญ่ขึ้น


2
ฉันคิดว่าระบบปฏิบัติการสมัยใหม่เลียนแบบหน่วยความจำต่อเนื่องสำหรับ. ตั้งแต่ 80486 สถาปัตยกรรม x86 จึงรองรับการเพจเพื่อให้ง่ายต่อการจัดเรียงหน่วยความจำฟิสิคัลใหม่
Mnementh

3
Mnemeth: ประการแรกมี API เฉพาะ (AllocateUserPhysicalPages) ใน WINAPI สำหรับเครื่องมือขั้นสูงเช่นฐานข้อมูลและ VM ที่ดีกว่าในการจัดการหน่วยความจำด้วยตัวเองด้วย Windows นอกทาง ประการที่สองการเพจเป็นคุณลักษณะโหมดป้องกัน 80386 ไม่ใช่ 80486
Tamas Czinege

6

JVM ของ Sun ต้องการหน่วยความจำที่ต่อเนื่องกัน ดังนั้นจำนวนหน่วยความจำสูงสุดที่มีอยู่จึงถูกกำหนดโดยการกระจายตัวของหน่วยความจำ โดยเฉพาะอย่างยิ่ง dll ของคนขับมีแนวโน้มที่จะแยกส่วนหน่วยความจำเมื่อโหลดไปยังที่อยู่ฐานที่กำหนดไว้ ดังนั้นฮาร์ดแวร์และไดรเวอร์ของคุณจะเป็นตัวกำหนดจำนวนหน่วยความจำที่คุณจะได้รับ

แหล่งข้อมูลสองแหล่งพร้อมคำแถลงจากวิศวกรของ Sun: บล็อกของฟอรัม

อาจจะเป็น JVM อื่น? คุณลองHarmony แล้วหรือยัง? ฉันคิดว่าพวกเขาวางแผนที่จะอนุญาตให้ใช้หน่วยความจำแบบไม่ต่อเนื่อง


แต่ฉันสามารถจัดสรร 1300MB บนเครื่องที่มี RAM เพียง 1GB (พร้อมหน่วยความจำเสมือน) เครื่อง RAM 2GB ของฉัน (รวมถึงหน่วยความจำเสมือนด้วย) สามารถจัดสรรได้เพียง 1200MB
Steve Kuo

Harmony is dead ใช่มั้ย?
Pacerier

ใช่: "Apache Harmony เกษียณแล้วที่ Apache Software Foundation ตั้งแต่วันที่ 16 พ.ย. 2554"
bobbel

3

ฉันคิดว่ามันเกี่ยวข้องกับการกำหนดค่า Windows ตามคำแนะนำโดยคำตอบนี้: Java -Xmx Option

การทดสอบเพิ่มเติม: ฉันสามารถจัดสรร 1300MB บนเครื่อง Windows XP รุ่นเก่าที่มี RAM จริงเพียง 768MB (พร้อมหน่วยความจำเสมือน) ในเครื่อง RAM 2GB ของฉันฉันสามารถรับได้เพียง 1220MB บนเครื่องขององค์กรอื่น ๆ (ที่ใช้ Windows XP รุ่นเก่า) ฉันสามารถรับได้ 1400MB เครื่องที่มีขีด จำกัด 1220MB นั้นค่อนข้างใหม่ (เพิ่งซื้อจาก Dell) ดังนั้นอาจมี Windows และ DLL ที่ใหม่กว่า (และป่องมากขึ้น) (ใช้ Window XP Pro เวอร์ชัน 2002 SP2)


อาจได้รับผลกระทบจากการตั้งค่าหน่วยความจำเสมือนของคุณด้วย
skaffman

เครื่องทั้งหมดที่ฉันทดสอบมีหน่วยความจำเสมือนอย่างน้อยสองเท่าของ RAM จริง
Steve Kuo

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

2

ฉันได้รับข้อความแสดงข้อผิดพลาดนี้เมื่อเรียกใช้โปรแกรม Java จาก Virtuozzo VPS (หน่วยความจำ จำกัด ) ผมไม่ได้ระบุข้อโต้แย้งหน่วยความจำใด ๆ และพบว่าผมมีการกำหนดอย่างชัดเจนขนาดเล็กจำนวนเงินที่เป็นค่าเริ่มต้นจะต้องได้รับสูงเกินไป เช่น -Xmx32m (แน่นอนว่าต้องปรับขึ้นอยู่กับโปรแกรมที่คุณเรียกใช้)

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


1

JDK / JRE ของ sun ต้องการหน่วยความจำที่ต่อเนื่องกันหากคุณจัดสรรบล็อกขนาดใหญ่

ระบบปฏิบัติการและแอปเริ่มต้นมักจะจัดสรรบิตและชิ้นส่วนระหว่างการโหลดซึ่งจะแยกส่วนของ RAM ที่มีอยู่ หากไม่มีบล็อกที่อยู่ติดกัน SUN JDK จะไม่สามารถใช้งานได้ JRockit จาก Bea (ได้มาโดย Oracle) สามารถจัดสรรหน่วยความจำจากชิ้นส่วนต่างๆ


1

ดูเหมือนทุกคนจะตอบเกี่ยวกับความจำที่ต่อเนื่องกัน แต่กลับละเลยที่จะรับทราบปัญหาเร่งด่วนมากกว่า

แม้จะมีการจัดสรรหน่วยความจำที่ต่อเนื่องกัน 100% คุณก็ไม่สามารถมีขนาดฮีป 2 GiB บนระบบปฏิบัติการ Windows 32 บิตได้ (* โดยค่าเริ่มต้น) เนื่องจากกระบวนการ Windows แบบ 32 บิตไม่สามารถระบุพื้นที่มากกว่า 2 GiB ได้

กระบวนการ Java จะประกอบด้วยดัด Gen (pre Java 8) ขนาดสแต็คต่อด้าย JVM / ค่าใช้จ่ายในห้องสมุด (ซึ่งเพิ่มขึ้นสวยมากกับการสร้างแต่ละ) ทั้งหมดนอกเหนือจากกอง

นอกจากนี้แฟล็ก JVM และค่าดีฟอลต์จะเปลี่ยนระหว่างเวอร์ชัน เพียงเรียกใช้สิ่งต่อไปนี้และคุณจะได้รับแนวคิด:

 java -XX:+PrintFlagsFinal

ตัวเลือกมากมายมีผลต่อการแบ่งหน่วยความจำเข้าและออกจากฮีป ปล่อยให้คุณมี 2 GiB ที่จะเล่นด้วยไม่มากก็น้อย ...

หากต้องการใช้ซ้ำบางส่วนของคำตอบนี้ของฉัน (เกี่ยวกับ Tomcat แต่ใช้กับกระบวนการ Java ใด ๆ ):

ระบบปฏิบัติการ Windows จำกัด การจัดสรรหน่วยความจำของกระบวนการ 32 บิตไว้ที่ 2 GiB ทั้งหมด (โดยค่าเริ่มต้น)

[คุณจะสามารถ] จัดสรรพื้นที่ฮีปประมาณ 1.5 GiB ได้เนื่องจากยังมีหน่วยความจำอื่น ๆ ที่จัดสรรให้กับกระบวนการนี้ (ค่าใช้จ่าย JVM / ไลบรารี

เหตุใด Windows 32 บิตจึงกำหนดขีด จำกัด พื้นที่แอดเดรสกระบวนการ 2 GB แต่ Windows 64 บิตกำหนดขีด จำกัด 4GB

ระบบปฏิบัติการสมัยใหม่อื่น ๆ [ไอลินุกซ์] อนุญาตให้โปรเซส 32 บิตใช้พื้นที่แอดเดรส 4 GiB ทั้งหมด (หรือเกือบทั้งหมด)

ที่กล่าวว่าระบบปฏิบัติการ Windows 64 บิตสามารถกำหนดค่าเพื่อเพิ่มขีด จำกัด ของกระบวนการ 32 บิตเป็น 4 GiB (3 GiB บน 32 บิต):

http://msdn.microsoft.com/en-us/library/windows/desktop/aa366778(v=vs.85).aspx


1
คำตอบนี้กล่าวถึงสาเหตุที่เขาสามารถจัดสรรได้เพียง 2 GB เท่านั้นไม่ใช่เหตุผลที่เขาสามารถจัดสรร 1.4 GB ในคอมพิวเตอร์เครื่องหนึ่งและเพียง 1.2 GB สำหรับอีกเครื่องหนึ่ง เขาไม่ถึงขีด จำกัด 1.5 GB, 2 GB หรือ 4 GB ที่ระบุไว้ที่นี่
vapcguy

1
ย่อหน้าบนแฟล็ก JVM อธิบายสาเหตุที่หน่วยความจำอาจแตกต่างกันระหว่างเวอร์ชัน นอกจากนี้โปรดสังเกตประเด็นของฉันว่าการตั้งค่าฮีปเป็นเศษส่วน (ขนาดใหญ่) ของขนาดกระบวนการทั้งหมดเสมอดังนั้นการตั้งค่าด้านล่างที่อาจถึงขีด จำกัด ของกระบวนการ 2 GiB - อีกอย่างหนึ่งอาจถูก จำกัด โดยการจัดสรรหน่วยความจำที่ต่อเนื่องกัน
Michael

หรืออาจถึงขีด จำกัด 1.5 GB สำหรับการจัดสรร 1.4 GB ที่เขากำลังทำอยู่ เข้าท่ากว่าตอนนี้ - ขอบคุณสำหรับคำชี้แจงนั้น
vapcguy

0

วิธีเพิ่มขนาดเพจจิ้งมีดังนี้

  1. คลิกขวาที่ mycomputer ---> properties ---> Advanced
  2. ในส่วนประสิทธิภาพคลิกการตั้งค่า
  3. คลิกแท็บขั้นสูง
  4. ในส่วนหน่วยความจำเสมือนคลิกเปลี่ยน มันจะแสดงขนาดเพจปัจจุบันของคุณ
  5. เลือกไดรฟ์ที่มีพื้นที่ว่างบนฮาร์ดดิสก์
  6. ระบุขนาดเริ่มต้นและขนาดสูงสุด ... เช่นขนาดเริ่มต้น 0 MB และขนาดสูงสุด 4000 MB (เท่าที่คุณต้องการ)

0

** มีหลายวิธีในการเปลี่ยนขนาดฮีปเช่น

  1. file-> setting-> build, exceution, deployment-> compiler ที่นี่คุณจะพบขนาดฮีป
  2. file-> setting-> build, exceution, deployment-> compiler-> andriodที่นี่คุณจะพบขนาดฮีป คุณสามารถอ้างอิงสิ่งนี้สำหรับโครงการ andriod หากคุณประสบปัญหาเดียวกัน

สิ่งที่ได้ผลสำหรับฉันคือ

  1. ตั้งค่าพา ธ JAVA_HOME ที่เหมาะสมในกรณีที่คุณได้รับการอัปเดต java

  2. สร้างตัวแปรระบบใหม่คอมพิวเตอร์ -> คุณสมบัติ -> การตั้งค่าขั้นสูง - > สร้างตัวแปรระบบใหม่

ชื่อ: _JAVA_OPTION ค่า: -Xmx750m

FYI: คุณสามารถค้นหา VMoption เริ่มต้นได้ใน Intellij help- > แก้ไขตัวเลือก VM ที่กำหนดเองในไฟล์นี้คุณจะเห็นขนาดฮีปขั้นต่ำและสูงสุด **


-1

ขั้นแรกการใช้ไฟล์เพจเมื่อคุณมี RAM 4 GB นั้นไร้ประโยชน์ Windows ไม่สามารถเข้าถึงได้มากกว่า 4GB (จริงๆแล้วน้อยกว่าเนื่องจากรูหน่วยความจำ) ดังนั้นจึงไม่ได้ใช้ไฟล์เพจ

ประการที่สองพื้นที่แอดเดรสแบ่งเป็น 2 ครึ่งสำหรับเคอร์เนลครึ่งหนึ่งสำหรับโหมดผู้ใช้ หากคุณต้องการ RAM เพิ่มเติมสำหรับแอปพลิเคชันของคุณให้ใช้ตัวเลือก / 3GB ใน boot.ini (ตรวจสอบให้แน่ใจว่า java.exe ถูกทำเครื่องหมายเป็น "ที่อยู่ขนาดใหญ่ที่ทราบ" (google สำหรับข้อมูลเพิ่มเติม)

ประการที่สามฉันคิดว่าคุณไม่สามารถจัดสรรพื้นที่ที่อยู่เต็ม 2 GB ได้เนื่องจาก java เสียหน่วยความจำภายใน (สำหรับเธรดคอมไพเลอร์ JIT การเริ่มต้น VM ฯลฯ ) ใช้สวิตช์ / 3GB เพื่อดูข้อมูลเพิ่มเติม


1
ความคิดที่ว่าไฟล์เพจไร้ประโยชน์กับ 4GB หรือ RAM นั้นไม่ถูกต้อง หากไม่มีไฟล์เพจระบบปฏิบัติการจะไม่สามารถขับไล่ข้อมูลกระบวนการที่ไม่ได้ใช้งาน (พื้นที่สแต็กสำหรับบริการที่ไม่ได้ใช้งาน ฯลฯ ) ออกจาก RAM จริงซึ่งจะช่วยลดจำนวน RAM ที่พร้อมใช้งานสำหรับการทำงานจริง การมี pagefile จะทำให้ RAM ว่าง
ไม่มีใคร
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.