Memória máxima de Java no Windows XP

103

Sempre consegui alocar 1400 megabytes para Java SE rodando no Windows XP de 32 bits (Java 1.4, 1.5 e 1.6).

java -Xmx1400m ...

Hoje tentei a mesma opção em uma nova máquina Windows XP usando Java 1.5_16 e 1.6.0_07 e recebi o erro:

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

Por tentativa e erro, parece que 1200 megabytes é o máximo que posso alocar nesta máquina.

Alguma idéia de por que uma máquina permitiria 1400 e outra apenas 1200?

Editar: A máquina tem 4 GB de RAM com cerca de 3,5 GB que o Windows pode reconhecer.

Steve Kuo
fonte
Você notaria uma diferença no máximo entre executar o aplicativo em um shell de 32 bits ou em um shell de 64 bits, pelo menos na minha experiência, embora os sistemas WindowsXP de 64 bits sejam raros.
djangofan

Respostas:

124

Lembre-se de que o Windows possui gerenciamento de memória virtual e a JVM precisa apenas de memória contígua em seu espaço de endereço . Portanto, outros programas em execução no sistema não devem necessariamente impactar o tamanho do heap. O que vai atrapalhar são as DLLs que são carregadas no seu espaço de endereço. Infelizmente, as otimizações no Windows que minimizam a realocação de DLLs durante a vinculação tornam mais provável que você tenha um espaço de endereço fragmentado. Coisas que provavelmente invadirão seu espaço de endereço, além do material normal, incluem software de segurança, software CBT, spyware e outras formas de malware. As causas prováveis ​​das variações são diferentes patches de segurança, versões de tempo de execução C, etc. Os drivers de dispositivo e outros bits de kernel têm seu próprio espaço de endereço (os outros 2 GB do espaço de 4 GB de 32 bits).

Você pode tentar passar por suas ligações de DLL em seu processo JVM e tentar rebase suas DLLs em um espaço de endereço mais compacto. Não é divertido, mas se você está desesperado ...

Como alternativa, você pode simplesmente mudar para o Windows de 64 bits e uma JVM de 64 bits. Apesar do que outros sugeriram, embora consuma mais RAM, você terá muito mais espaço de endereço virtual contíguo, e alocar 2 GB de forma contígua seria trivial.

Christopher Smith
fonte
5
Use o Process Explorer para ver onde as dll da memória estão sendo carregadas. Freqüentemente, algum driver atualizado ficará no meio do seu espaço de endereço. Usando o comando REBASE, você pode facilmente removê-los do caminho. Porém, tenha em mente que a dll está sujeita a ser atualizada novamente e a interromper as coisas.
brianegge
2
Eu nunca aceitei isso como uma resposta e ainda stackoverflow marcou como respondido.
Steve Kuo
@Christopher, É possível usar JVM de 64 bits em um Windows XP de 32 bits?
Pacerier
@Pacerier Desculpe, perdi sua consulta. AFAIK, não é possível. O OS X tinha alguns truques para o espaço do usuário de 64 bits com kernels de 32 bits, mas nunca ouvi falar de tal coisa para o Windows.
Christopher Smith
@ChristopherSmith, Btw, você mencionou " outros programas em execução no sistema não devem necessariamente impactar o tamanho do heap ". Em caso afirmativo, como explicamos esse resultado: stackoverflow.com/questions/9303889/… ?
Pacerier
50

Isso tem a ver com a memória contígua.

Aqui estão algumas informações que encontrei online para alguém que perguntou isso antes, supostamente de um "deus VM":

O motivo pelo qual precisamos de uma região de memória contígua para o heap é que temos um monte de estruturas de dados colaterais que são indexadas por deslocamentos (escalonados) desde o início do heap. Por exemplo, rastreamos atualizações de referência de objeto com uma "matriz de marca de cartão" que tem um byte para cada 512 bytes de heap. Quando armazenamos uma referência no heap, temos que marcar o byte correspondente na matriz de marca do cartão. Mudamos para a direita o endereço de destino da loja e usamos isso para indexar a matriz de marca do cartão. É divertido lidar com jogos aritméticos que você não pode fazer em Java e que consegue (tem que :-) jogar em C ++.

Normalmente não temos problemas para obter regiões contíguas modestas (até cerca de 1,5 GB no Windohs, até cerca de 3,8 GB no Solaris. YMMV.). No Windohs, o problema é principalmente que existem algumas bibliotecas que são carregadas antes da inicialização da JVM que dividem o espaço de endereço. Usar a opção / 3GB não fará o rebase dessas bibliotecas, então elas ainda são um problema para nós.

Nós sabemos como fazer pilhas fragmentadas, mas haveria alguma sobrecarga para usá-las. Temos mais solicitações para gerenciamento de armazenamento mais rápido do que para heaps maiores na JVM de 32 bits. Se você realmente deseja pilhas grandes, mude para a JVM de 64 bits. Ainda precisamos de memória contígua, mas é muito mais fácil entrar em um espaço de endereço de 64 bits.

Uri
fonte
Isso é muito interessante. Sempre me perguntei por que 1500 MB, agora entendi, obrigado!
Tim Büthe,
3
Desculpe por responder a uma pergunta muito antiga, mas esta é a melhor resposta que eu já vi até agora. Mas por que a JVM falha na inicialização se não pode obter o tamanho máximo de heap? Não deveria se contentar silenciosamente com o melhor tamanho acima do mínimo ?
Stroboskop
19

Os limites de tamanho de heap Java para Windows são:

  • tamanho de heap máximo possível em Java de 32 bits: 1,8 GB
  • limite de tamanho de heap recomendado em Java de 32 bits: 1,5 GB (ou 1,8 GB com opção / 3 GB)

Isso não o ajuda a obter um heap Java maior, mas agora você sabe que não pode ir além desses valores.

MicSim
fonte
10

O Oracle JRockit , que pode manipular um heap não contíguo, pode ter um tamanho de heap Java de 2,85 GB no Windows 2003 / XP com a opção / 3GB. Parece que a fragmentação pode ter um grande impacto sobre o quão grande pode ser um heap Java.

Kire Haglin
fonte
6

A JVM precisa de memória contígua e dependendo do que mais está sendo executado, do que estava sendo executado antes e de como o Windows gerencia a memória, você pode conseguir até 1,4 GB de memória contígua. Acho que o Windows de 64 bits permitirá pilhas maiores.

James AN Stauffer
fonte
2
Acho que o sistema operacional moderno emula memória contínua para o. Desde o 80486, a arquitetura x86 oferece suporte à paginação para facilitar a reorganização da memória física.
Mnementh
3
Mnemeth: Primeiro, há uma API específica (AllocateUserPhysicalPages) no WINAPI para ferramentas avançadas como bancos de dados e VMs que são melhores com o gerenciamento de sua própria memória com o Windows fora do caminho. Em segundo lugar, o paging é um recurso do modo protegido 80386, não 80486.
Tamas Czinege
6

A JVM da Sun precisa de memória contígua. Portanto, a quantidade máxima de memória disponível é ditada pela fragmentação da memória. Especialmente as dlls do driver tendem a fragmentar a memória, ao carregar em algum endereço de base predefinido. Portanto, seu hardware e seus drivers determinam quanta memória você pode obter.

Duas fontes para isso com declarações de engenheiros da Sun: blog do fórum

Talvez outro JVM? Você já experimentou o Harmony ? Acho que eles planejaram permitir a memória não contínua.

the.duckman
fonte
Mas consegui alocar 1300 MB em uma máquina com apenas 1 GB de RAM (mais memória virtual). Minha máquina de 2 GB de RAM (também com memória virtual) pode alocar apenas 1200 MB.
Steve Kuo,
Harmony está morta, não é?
Pacerier
Sim: "Apache Harmony está aposentado na Apache Software Foundation desde 16 de novembro de 2011."
bobbel de
3

Acho que tem mais a ver com a configuração do Windows, conforme sugerido por esta resposta: Java -Xmx Option

Mais alguns testes: Consegui alocar 1300 MB em uma máquina antiga do Windows XP com apenas 768 MB de RAM física (mais memória virtual). Na minha máquina de 2 GB de RAM, só consigo 1220 MB. Em várias outras máquinas corporativas (com o Windows XP mais antigo), consegui 1400 MB. A máquina com um limite de 1220 MB é muito nova (recém-adquirida da Dell), então talvez ela tenha Windows e DLLs mais recentes (e mais inchados) (está executando o Windows XP Pro versão 2002 SP2).

Steve Kuo
fonte
Ele também pode ser afetado pelas configurações de memória virtual.
Skaffman
Todas as máquinas com as quais testei têm memória virtual pelo menos o dobro da RAM física.
Steve Kuo,
note que você realmente nunca vai querer usar memória virtual com java, porque o desempenho do GC ficará muito ruim. A quantidade de memória depende de quais dlls já foram carregadas e fragmentaram a memória.
kohlerm
2

Recebi esta mensagem de erro ao executar um programa java a partir de um VPS virtuozzo (memória limitada). Não especifiquei nenhum argumento de memória e descobri que precisava definir explicitamente uma pequena quantidade, pois o padrão devia ser muito alto. Por exemplo, -Xmx32m (obviamente precisa ser ajustado dependendo do programa que você executa).

Basta colocar isso aqui no caso de alguém receber a mensagem de erro acima sem especificar uma grande quantidade de memória como o questionador fez.

William Denniss
fonte
1

O JDK / JRE da sun precisa de uma quantidade contígua de memória se você alocar um bloco grande.

O sistema operacional e os aplicativos iniciais tendem a alocar bits e peças durante o carregamento, o que fragmenta a RAM disponível. Se um bloco contíguo NÃO estiver disponível, o SUN JDK não poderá usá-lo. JRockit de Bea (adquirido pela Oracle) pode alocar memória de peças.

Anjanb
fonte
1

Todo mundo parece estar respondendo sobre a memória contígua, mas negligenciou o reconhecimento de uma questão mais urgente.

Mesmo com 100% de alocação de memória contígua, você não pode ter um tamanho de heap de 2 GiB em um sistema operacional Windows de 32 bits (* por padrão). Isso ocorre porque os processos do Windows de 32 bits não podem lidar com mais de 2 GiB de espaço.

O processo Java conterá perm gen (pré Java 8), tamanho da pilha por encadeamento, sobrecarga de JVM / biblioteca (que praticamente aumenta com cada construção), tudo além do heap .

Além disso, os sinalizadores de JVM e seus valores padrão mudam entre as versões. Basta executar o seguinte e você terá uma ideia:

 java -XX:+PrintFlagsFinal

Muitas opções afetam a divisão de memória dentro e fora do heap. Deixando você com mais ou menos daqueles 2 GiB para brincar ...

Para reutilizar partes desta minha resposta (sobre Tomcat, mas se aplica a qualquer processo Java):

O sistema operacional Windows limita a alocação de memória de um processo de 32 bits a 2 GiB no total (por padrão).

[Você só poderá] alocar cerca de 1,5 GiB de espaço de heap porque também há outra memória alocada para o processo (JVM / sobrecarga de biblioteca, espaço de perm gen etc.).

Por que o Windows de 32 bits impõe um limite de espaço de endereço de processo de 2 GB, mas o Windows de 64 bits impõe um limite de 4 GB?

Outros sistemas operacionais modernos [cough Linux] permitem que os processos de 32 bits usem todo (ou a maioria) do espaço endereçável de 4 GiB.

Dito isso, os sistemas operacionais Windows de 64 bits podem ser configurados para aumentar o limite de processos de 32 bits para 4 GiB (3 GiB em 32 bits):

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

Michael
fonte
1
Esta resposta aborda apenas por que ele só pode alocar 2 GB, não por que ele pode alocar 1,4 GB em um computador e apenas 1,2 GB em outro. Ele não atingiu seus limites de 1,5 GB, 2 GB ou 4 GB declarados aqui.
vapcguy
1
O parágrafo sobre sinalizadores JVM explica de alguma forma porque a memória pode variar entre as versões. Além disso, observe meu ponto sobre como a configuração de heap é sempre uma (grande) fração do tamanho total do processo - portanto, uma configuração abaixo que ainda pode atingir o limite de processo de 2 GiB - outra pode ser restringida pela alocação de memória contígua.
Michael
Ou possivelmente o limite de 1,5 GB, naquela alocação de 1,4 GB que ele está fazendo. Faz mais sentido agora - obrigado por esse esclarecimento.
vapcguy
0

Aqui está como aumentar o tamanho da paginação

  1. clique com o botão direito em mycomputer ---> propriedades ---> Advanced
  2. na seção de desempenho, clique em configurações
  3. clique na guia Avançado
  4. na seção de memória virtual, clique em alterar. Ele mostrará seu tamanho de paginação atual.
  5. Selecione Drive onde o espaço do HDD estiver disponível.
  6. Forneça o tamanho inicial e máximo ... por exemplo, tamanho inicial 0 MB e tamanho máximo 4000 MB. (O quanto você precisar)
Israel Margulies
fonte
0

** Existem várias maneiras de alterar o tamanho do heap, como,

  1. arquivo-> configuração-> construção, exceção, implantação-> compilador aqui você encontrará o tamanho do heap
  2. arquivo-> configuração-> construção, exceção, implantação-> compilador-> andriod aqui também você encontrará o tamanho do heap. Você pode consultar isso para o projeto andriod se estiver enfrentando o mesmo problema.

O que funcionou para mim foi

  1. Defina o caminho JAVA_HOME apropriado caso o java tenha sido atualizado.

  2. criar uma nova variável de sistema -> propriedades - > configuração avançada - > criar uma nova variável de sistema

nome: _JAVA_OPTION valor: -Xmx750m

Para sua informação: você pode encontrar a opção VM padrão em Ajuda do Intellij- > editar a opção VM personalizada . Neste arquivo, você vê o tamanho mínimo e máximo do heap. **

Akanksha gore
fonte
-1

Primeiro, usar um arquivo de paginação quando você tem 4 GB de RAM é inútil. O Windows não pode acessar mais do que 4 GB (na verdade, menos devido a falhas de memória), portanto, o arquivo de página não é usado.

Em segundo lugar, o espaço de endereço é dividido em 2, metade para o kernel e metade para o modo de usuário. Se precisar de mais RAM para seus aplicativos, use a opção / 3GB em boot.ini (certifique-se de que java.exe esteja marcado como "ciente de endereço grande" (google para obter mais informações).

Terceiro, acho que você não pode alocar os 2 GB completos de espaço de endereço porque o java desperdiça alguma memória internamente (para threads, compilador JIT, inicialização de VM, etc). Use a opção / 3GB para mais.

user17544
fonte
1
A ideia de um arquivo de paginação ser inútil com 4 GB ou RAM está errada. Sem um arquivo de paginação, o sistema operacional não pode despejar dados de processo não utilizados (espaço de pilha para serviços não utilizados, etc.) da RAM física, reduzindo assim a quantidade de RAM disponível para trabalho real. Ter um arquivo de paginação libera RAM.
ninguém