Bộ nhớ tối đa Java trên Windows XP


103

Tôi luôn có thể phân bổ 1400 megabyte cho Java SE chạy trên Windows XP 32 bit (Java 1.4, 1.5 và 1.6).

java -Xmx1400m ...

Hôm nay, tôi đã thử tùy chọn tương tự trên máy Windows XP mới sử dụng Java 1.5_16 và 1.6.0_07 và gặp lỗi:

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

Thông qua thử nghiệm và lỗi, có vẻ như 1200 megabyte là tối đa mà tôi có thể phân bổ trên máy này.

Bất kỳ ý tưởng tại sao một máy sẽ cho phép 1400 và máy khác chỉ 1200?

Chỉnh sửa: Máy có 4GB RAM với khoảng 3.5GB mà Windows có thể nhận diện được.


Bạn sẽ nhận thấy sự khác biệt về mức tối đa giữa việc chạy ứng dụng trong trình bao 32 bit hoặc trình bao 64 bit, ít nhất là theo kinh nghiệm của tôi, mặc dù hệ thống WindowsXP 64 bit là rất hiếm.
djangofan

Câu trả lời:


124

Hãy nhớ rằng Windows có quản lý bộ nhớ ảo và JVM chỉ cần bộ nhớ liền kề trong không gian địa chỉ của nó . Vì vậy, các chương trình khác đang chạy trên hệ thống không nhất thiết phải ảnh hưởng đến kích thước heap của bạn. Những gì sẽ cản trở bạn là các DLL được tải vào vùng địa chỉ của bạn. Thật không may, các tối ưu hóa trong Windows giảm thiểu việc di chuyển các DLL trong quá trình liên kết khiến nhiều khả năng bạn sẽ có một không gian địa chỉ bị phân mảnh. Những thứ có thể xâm phạm không gian địa chỉ của bạn ngoài những thứ thông thường bao gồm phần mềm bảo mật, phần mềm CBT, phần mềm gián điệp và các dạng phần mềm độc hại khác. Nguyên nhân có thể gây ra sự khác biệt là các bản vá bảo mật khác nhau, phiên bản thời gian chạy C, v.v. Trình điều khiển thiết bị và các bit hạt nhân khác có không gian địa chỉ riêng (2GB còn lại của không gian 4GB 32 bit).

Bạn có thể thử xem xét các ràng buộc DLL của mình trong quy trình JVM và xem xét việc cố gắng căn cứ lại DLL của bạn vào một không gian địa chỉ nhỏ gọn hơn. Không vui, nhưng nếu bạn đang tuyệt vọng ...

Ngoài ra, bạn có thể chỉ cần chuyển sang Windows 64 bit và JVM 64 bit. Mặc dù những gì người khác đã đề xuất, mặc dù nó sẽ ngốn nhiều RAM hơn, nhưng bạn sẽ có nhiều không gian địa chỉ ảo liền kề hơn và việc phân bổ 2GB liên tục sẽ là không đáng kể.


5
Sử dụng Process Explorer để xem nơi đang tải dll bộ nhớ. Thường thì một số trình điều khiển được cập nhật sẽ tự dính vào giữa không gian địa chỉ của bạn. Sử dụng lệnh REBASE, bạn có thể dễ dàng đẩy chúng ra khỏi đường đi. Tuy nhiên, hãy nhớ rằng dll có thể được cập nhật lại và phá vỡ mọi thứ.
brianegge

2
Tôi chưa bao giờ chấp nhận đây là một câu trả lời và nhưng stackoverflow đã đánh dấu nó là đã trả lời.
Steve Kuo

@Christopher, Có thể sử dụng JVM 64 bit trên Windows XP 32 bit không?
Pacerier

@Pacerier Xin lỗi, tôi đã bỏ qua truy vấn của bạn. AFAIK, điều đó là không thể. OS X có một số thủ thuật cho không gian người dùng 64-bit với nhân 32-bit, nhưng tôi chưa nghe nói về bất kỳ điều gì như vậy cho Windows.
Christopher Smith

@ChristopherSmith, Btw, bạn đã đề cập đến " các chương trình khác chạy trên hệ thống không nhất thiết phải ảnh hưởng đến kích thước đống của bạn ". Nếu vậy, chúng tôi giải thích kết quả này như thế nào: stackoverflow.com/questions/9303889/… ?
Pacerier

50

Điều này phải làm với bộ nhớ liền kề.

Đây là một số thông tin tôi tìm thấy trực tuyến cho một người nào đó đã hỏi điều đó trước đây, được cho là từ một "thần máy ảo":

Lý do chúng ta cần một vùng bộ nhớ liền kề cho heap là chúng ta có một loạt các cấu trúc dữ liệu bên được lập chỉ mục theo các hiệu số (được chia tỷ lệ) từ đầu heap. Ví dụ: chúng tôi theo dõi các cập nhật tham chiếu đối tượng bằng "mảng dấu thẻ" có một byte cho mỗi 512 byte heap. Khi chúng ta lưu trữ một tham chiếu trong heap, chúng ta phải đánh dấu byte tương ứng trong mảng dấu thẻ. Chúng ta phải thay đổi địa chỉ đích của cửa hàng và sử dụng địa chỉ đó để lập chỉ mục mảng đánh dấu thẻ. Giải quyết các trò chơi số học thú vị mà bạn không thể làm trong Java mà bạn có được (phải :-) chơi bằng C ++.

Thông thường, chúng tôi không gặp khó khăn khi nhận được các vùng tiếp giáp khiêm tốn (tối đa khoảng 1,5 GB trên Windohs, lên đến khoảng 3,8 GB trên Solaris. YMMV.). Trên Windohs, vấn đề chủ yếu là có một số thư viện được tải trước khi JVM khởi động làm phá vỡ không gian địa chỉ. Việc sử dụng chuyển đổi / 3GB sẽ không căn cứ lại các thư viện đó, vì vậy chúng vẫn là một vấn đề đối với chúng tôi.

Chúng tôi biết cách tạo ra các đống nhỏ, nhưng sẽ có một số chi phí để sử dụng chúng. Chúng tôi có nhiều yêu cầu hơn để quản lý bộ nhớ nhanh hơn so với yêu cầu đối với đống lớn hơn trong JVM 32-bit. Nếu bạn thực sự muốn đống lớn, hãy chuyển sang JVM 64-bit. Chúng ta vẫn cần bộ nhớ liền kề, nhưng việc sử dụng không gian địa chỉ 64-bit sẽ dễ dàng hơn nhiều.


Điều đó rất thú vị. Tôi luôn tự hỏi bản thân tại sao 1500 MB, bây giờ tôi đã nhận được nó, cảm ơn!
Tim Büthe

3
Xin lỗi vì đã theo dõi một câu hỏi cũ, nhưng đây là câu trả lời hay nhất mà tôi thấy cho đến nay. Nhưng tại sao JVM không thành công khi khởi động nếu nó không thể nhận được kích thước đống tối đa ? Nó không nên lặng lẽ giải quyết cho kích thước tốt nhất trên mức tối thiểu ?
Stroboskop,

19

Giới hạn kích thước heap Java cho Windows là:

  • kích thước đống tối đa có thể có trên Java 32-bit: 1,8 GB
  • giới hạn kích thước heap được đề xuất trên Java 32-bit: 1,5 GB (hoặc 1,8 GB với tùy chọn / 3GB)

Điều này không giúp bạn nhận được một đống Java lớn hơn, nhưng bây giờ bạn biết rằng bạn không thể vượt quá những giá trị này.


10

Oracle JRockit , có thể xử lý một heap không liền kề, có thể có kích thước heap Java là 2,85 GB trên Windows 2003 / XP với công tắc / 3GB. Có vẻ như sự phân mảnh có thể có tác động khá lớn đến mức độ lớn của một đống Java.


6

JVM cần bộ nhớ liền kề và tùy thuộc vào những gì khác đang chạy, những gì đã chạy trước đó và cách cửa sổ quản lý bộ nhớ, bạn có thể nhận được tối đa 1,4 GB bộ nhớ liền kề. Tôi nghĩ Windows 64bit sẽ cho phép các heap lớn hơn.


2
Tôi nghĩ rằng hệ điều hành hiện đại mô phỏng bộ nhớ liên tục cho. Kể từ 80486, kiến ​​trúc x86 hỗ trợ phân trang để giúp dễ dàng sắp xếp lại bộ nhớ vật lý.
Mnementh

3
Mnemeth: Đầu tiên, có một API cụ thể (AllocateUserPhysicalPages) trong WINAPI dành cho các công cụ nâng cao như cơ sở dữ liệu và máy ảo, tốt hơn với việc tự quản lý bộ nhớ của chúng với Windows. Thứ hai, phân trang là một tính năng 80386 chế độ bảo vệ, không 80486.
Tamas Czinege

6

JVM của Sun cần bộ nhớ liền kề. Vì vậy, lượng bộ nhớ khả dụng tối đa được quyết định bởi sự phân mảnh bộ nhớ. Đặc biệt là các ổ đĩa của trình điều khiển có xu hướng phân mảnh bộ nhớ, khi tải vào một số địa chỉ cơ sở được xác định trước. Vì vậy, phần cứng của bạn và trình điều khiển của nó quyết định lượng bộ nhớ bạn có thể nhận được.

Hai nguồn cho điều này với tuyên bố từ các kỹ sư của Sun: blog diễn đàn

Có thể là một JVM khác? Bạn đã thử Harmony chưa? Tôi nghĩ họ đã lên kế hoạch cho phép bộ nhớ không liên tục.


Nhưng tôi đã có thể phân bổ 1300MB trên máy chỉ có 1GB RAM (cộng với bộ nhớ ảo). Máy RAM 2GB của tôi (cũng có bộ nhớ ảo) chỉ có thể phân bổ 1200MB.
Steve Kuo

Hài hòa là chết phải không?
Pacerier

Đúng: "Apache Harmony đã ngừng hoạt động tại Apache Software Foundation kể từ ngày 16 tháng 11 năm 2011."
bobbel

3

Tôi nghĩ nó liên quan nhiều hơn đến cách Windows được cấu hình như được gợi ý trong phản hồi này: Java -Xmx Option

Một số thử nghiệm khác: Tôi có thể phân bổ 1300MB trên máy Windows XP cũ chỉ có RAM vật lý 768MB (cộng với bộ nhớ ảo). Trên máy RAM 2GB của tôi, tôi chỉ có thể nhận được 1220MB. Trên nhiều máy công ty khác (với Windows XP cũ hơn), tôi có thể nhận được 1400MB. Máy có giới hạn 1220MB là khá mới (vừa mua từ Dell), vì vậy có thể nó có Windows và DLL mới hơn (và cồng kềnh hơn) (đang chạy Window XP Pro Version 2002 SP2).


Nó cũng có thể bị ảnh hưởng bởi cài đặt Bộ nhớ ảo của bạn.
skaffman

Tất cả các máy tôi kiểm tra đều có bộ nhớ ảo ít nhất gấp đôi RAM vật lý.
Steve Kuo

lưu ý rằng bạn thực sự không bao giờ muốn thực sự sử dụng bộ nhớ ảo với java, bởi vì hiệu suất GC sẽ trở nên rất tệ. Dung lượng bộ nhớ phụ thuộc vào dll nào đã được tải và đã phân mảnh bộ nhớ.
kohlerm 18/10/08

2

Tôi nhận được thông báo lỗi này khi chạy chương trình java từ VPS (bộ nhớ hạn chế) ảo ảo VPS. Tôi đã không chỉ định bất kỳ đối số bộ nhớ nào và thấy rằng tôi phải đặt một cách rõ ràng một số lượng nhỏ vì giá trị mặc định phải quá cao. Ví dụ -Xmx32m (rõ ràng cần được điều chỉnh tùy thuộc vào chương trình bạn chạy).

Chỉ cần đặt điều này ở đây trong trường hợp bất kỳ ai khác nhận được thông báo lỗi ở trên mà không chỉ định dung lượng bộ nhớ lớn như người hỏi đã làm.


1

sun's JDK / JRE cần một lượng bộ nhớ liền kề nếu bạn phân bổ một khối lớn.

Hệ điều hành và các ứng dụng ban đầu có xu hướng phân bổ các bit và mảnh trong quá trình tải làm phân mảnh RAM khả dụng. Nếu KHÔNG có một khối liền kề, SUN JDK không thể sử dụng nó. JRockit của Bea (được Oracle mua lại) có thể cấp phát bộ nhớ từ các mảnh.


1

Mọi người dường như đang trả lời về bộ nhớ liền kề, nhưng đã bỏ qua việc thừa nhận một vấn đề cấp bách hơn.

Ngay cả khi phân bổ bộ nhớ liền kề 100%, bạn không thể có kích thước heap 2 GiB trên HĐH Windows 32 bit (* theo mặc định). Điều này là do các quy trình Windows 32-bit không thể giải quyết nhiều hơn 2 GiB dung lượng.

Quy trình Java sẽ bao gồm gen perm (trước Java 8), kích thước ngăn xếp trên mỗi luồng, chi phí JVM / thư viện (tăng khá nhiều với mỗi bản dựng), tất cả cùng với heap .

Hơn nữa, cờ JVM và giá trị mặc định của chúng thay đổi giữa các phiên bản. Chỉ cần chạy phần sau và bạn sẽ có một số ý tưởng:

 java -XX:+PrintFlagsFinal

Rất nhiều tùy chọn ảnh hưởng đến việc phân chia bộ nhớ trong và ngoài heap. Để lại cho bạn nhiều hơn hoặc ít hơn 2 GiB đó để chơi với ...

Để sử dụng lại các phần của câu trả lời này của tôi (về Tomcat, nhưng áp dụng cho bất kỳ quy trình Java nào):

Hệ điều hành Windows giới hạn phân bổ bộ nhớ của quy trình 32-bit tổng cộng là 2 GiB (theo mặc định).

[Bạn sẽ chỉ có thể] cấp phát khoảng 1,5 GiB không gian heap vì cũng có bộ nhớ khác được phân bổ cho quá trình (chi phí JVM / thư viện, không gian gen perm, v.v.).

Tại sao Windows 32 bit áp đặt giới hạn không gian địa chỉ quy trình 2 GB, nhưng Windows 64 bit lại áp đặt giới hạn 4GB?

Các hệ điều hành hiện đại khác [ho Linux] cho phép các quy trình 32-bit sử dụng tất cả (hoặc hầu hết) không gian địa chỉ 4 GiB.

Điều đó nói rằng, hệ điều hành Windows 64-bit có thể được cấu hình để tăng giới hạn của các quy trình 32-bit lên 4 GiB (3 GiB trên 32-bit):

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


1
Câu trả lời này chỉ giải quyết lý do tại sao anh ta chỉ có thể phân bổ 2 GB, chứ không phải tại sao anh ta có thể phân bổ 1,4 GB trên một máy tính và chỉ 1,2 GB trên máy tính khác. Anh ấy không đạt đến giới hạn 1,5 GB, 2 GB hoặc 4 GB của bạn được nêu ở đây.
vapcguy

1
Đoạn trên cờ JVM giải thích lý do tại sao bộ nhớ có thể khác nhau giữa các phiên bản. Ngoài ra, hãy lưu ý quan điểm của tôi về cách cài đặt heap luôn là một phần nhỏ (lớn) của tổng kích thước quy trình - vì vậy, một cài đặt bên dưới có thể vẫn đạt đến giới hạn quy trình 2 GiB - một cài đặt khác có thể bị hạn chế bởi phân bổ bộ nhớ liền kề.
Michael

Hoặc có thể là giới hạn 1,5 GB, trên phân bổ 1,4 GB mà anh ta đang thực hiện. Bây giờ có ý nghĩa hơn - cảm ơn đã làm rõ điều đó.
vapcguy

0

Đây là cách tăng kích thước phân trang

  1. nhấp chuột phải vào mycomputer ---> thuộc tính ---> Advanced
  2. trong phần hiệu suất nhấp vào cài đặt
  3. nhấp vào tab Nâng cao
  4. trong phần Bộ nhớ ảo, nhấp vào thay đổi. Nó sẽ hiển thị kích thước phân trang hiện tại của bạn.
  5. Chọn Ổ đĩa nơi có dung lượng ổ cứng.
  6. Cung cấp kích thước ban đầu và kích thước tối đa ... ví dụ: kích thước ban đầu 0 MB và kích thước tối đa 4000 MB. (Nhiều như bạn sẽ yêu cầu)

0

** Có nhiều cách để thay đổi kích thước đống như,

  1. file-> setting-> build, exceution, deploy-> compiler ở đây bạn sẽ tìm thấy kích thước heap
  2. file-> setting-> build, exceution, deploy-> compiler-> andriod ở đây bạn cũng sẽ tìm thấy kích thước heap. Bạn có thể tham khảo điều này cho dự án andriod nếu bạn gặp phải vấn đề tương tự.

Điều làm việc cho tôi là

  1. Đặt đường dẫn JAVA_HOME thích hợp trong trường hợp java của bạn đã được cập nhật.

  2. tạo máy tính biến hệ thống mới-> thuộc tính-> cài đặt nâng cao- > tạo biến hệ thống mới

tên: _JAVA_OPTION giá trị: -Xmx750m

FYI: bạn có thể tìm thấy VMoption mặc định trong trợ giúp Intellij- > chỉnh sửa tùy chọn VM tùy chỉnh , Trong tệp này, bạn thấy kích thước tối thiểu và tối đa của heap. **


-1

Đầu tiên, việc sử dụng tệp trang khi bạn có RAM 4 GB là vô ích. Windows không thể truy cập nhiều hơn 4GB (thực tế là ít hơn do lỗ bộ nhớ) nên tệp trang không được sử dụng.

Thứ hai, không gian địa chỉ được chia làm 2, một nửa cho nhân, một nửa cho chế độ người dùng. Nếu bạn cần thêm RAM cho các ứng dụng của mình, hãy sử dụng tùy chọn / 3GB trong boot.ini (đảm bảo rằng java.exe được đánh dấu là "nhận biết địa chỉ lớn" (google để biết thêm thông tin).

Thứ ba, tôi nghĩ rằng bạn không thể cấp phát đầy đủ 2 GB không gian địa chỉ vì java lãng phí một số bộ nhớ trong nội bộ (cho các luồng, trình biên dịch JIT, khởi tạo VM, v.v.). Sử dụng nút chuyển / 3GB để biết thêm.


1
Ý tưởng về một tệp trang là vô dụng với 4GB hoặc RAM là sai. Nếu không có tệp trang, hệ điều hành không thể loại bỏ dữ liệu quy trình không sử dụng (không gian ngăn xếp cho các dịch vụ không sử dụng, v.v.) khỏi RAM vật lý, do đó làm giảm dung lượng RAM có sẵn cho công việc thực tế. Có một tệp trang sẽ giải phóng RAM.
không ai
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.