Memoria máxima de Java en Windows XP

103

Siempre he podido asignar 1400 megabytes para Java SE que se ejecuta en Windows XP de 32 bits (Java 1.4, 1.5 y 1.6).

java -Xmx1400m ...

Hoy probé la misma opción en una nueva máquina con Windows XP usando Java 1.5_16 y 1.6.0_07 y obtuve el error:

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

A través de prueba y error, parece que 1200 megabytes es lo máximo que puedo asignar en esta máquina.

¿Alguna idea de por qué una máquina permitiría 1400 y otra solo 1200?

Editar: la máquina tiene 4 GB de RAM con aproximadamente 3,5 GB que Windows puede reconocer.

Steve Kuo
fuente
Notaría una diferencia en el máximo entre ejecutar la aplicación en un shell de 32 bits o en un shell de 64 bits, al menos en mi experiencia, aunque los sistemas WindowsXP de 64 bits son raros.
djangofan

Respuestas:

124

Tenga en cuenta que Windows tiene administración de memoria virtual y la JVM solo necesita memoria contigua en su espacio de direcciones . Por lo tanto, otros programas que se ejecutan en el sistema no deberían necesariamente afectar el tamaño de su pila. Lo que se interpondrá en su camino son las DLL que se cargan en su espacio de direcciones. Desafortunadamente, las optimizaciones en Windows que minimizan la reubicación de DLL durante la vinculación hacen que sea más probable que tenga un espacio de direcciones fragmentado. Las cosas que probablemente se interpongan en su espacio de direcciones además de las cosas habituales incluyen software de seguridad, software CBT, software espía y otras formas de malware. Las causas probables de las variaciones son diferentes parches de seguridad, versiones en tiempo de ejecución de C, etc. Los controladores de dispositivos y otros bits del kernel tienen su propio espacio de direcciones (los otros 2 GB del espacio de 4 GB de 32 bits).

Usted podría tratar de ir a través de sus enlaces de DLL en su proceso de JVM y vistazo a tratar de rebasar el archivo DLL de adentro a un espacio de direcciones más compacto. No es divertido, pero si estás desesperado ...

Alternativamente, puede simplemente cambiar a Windows de 64 bits y una JVM de 64 bits. A pesar de lo que otros han sugerido, aunque consumirá más RAM, tendrá mucho más espacio de direcciones virtuales contiguas, y asignar 2GB contiguos sería trivial.

Christopher Smith
fuente
5
Use Process Explorer para ver en qué parte de la memoria se cargan las DLL. A menudo, algún controlador actualizado se pegará en el medio de su espacio de direcciones. Con el comando REBASE, puede quitarlos fácilmente del camino. Sin embargo, tenga en cuenta que el dll está sujeto a actualizarse nuevamente y romper cosas.
brianegge
2
Nunca acepté esto como una respuesta y, sin embargo, stackoverflow lo marcó como respondido.
Steve Kuo
@Christopher, ¿es posible usar JVM de 64 bits en un Windows XP de 32 bits?
Pacerier
@Pacerier Lo siento, me perdí tu consulta. AFAIK, no es posible. OS X tenía algunos trucos para el espacio de usuario de 64 bits con núcleos de 32 bits, pero no he oído hablar de nada parecido para Windows.
Christopher Smith
@ChristopherSmith, por cierto, mencionaste que " otros programas que se ejecutan en el sistema no deberían afectar necesariamente el tamaño de tu pila ". Si es así, ¿cómo explicamos este resultado: stackoverflow.com/questions/9303889/… ?
Pacerier
50

Esto tiene que ver con la memoria contigua.

Aquí hay información que encontré en línea para alguien que me preguntó eso antes, supuestamente de un "dios VM":

La razón por la que necesitamos una región de memoria contigua para el montón es que tenemos un montón de estructuras de datos laterales que están indexadas por compensaciones (escaladas) desde el inicio del montón. Por ejemplo, realizamos un seguimiento de las actualizaciones de referencias de objetos con una "matriz de marcas de tarjeta" que tiene un byte por cada 512 bytes de montón. Cuando almacenamos una referencia en el montón, tenemos que marcar el byte correspondiente en la matriz de marcas de tarjeta. Cambiamos a la derecha la dirección de destino de la tienda y la usamos para indexar la matriz de marcas de tarjetas. Divertidos juegos aritméticos de direcciones que no puedes hacer en Java y que tienes que :-) jugar en C ++.

Por lo general, no tenemos problemas para obtener regiones contiguas modestas (hasta aproximadamente 1,5 GB en Windohs, hasta aproximadamente 3,8 GB en Solaris. YMMV.). En Windohs, el problema es principalmente que hay algunas bibliotecas que se cargan antes de que se inicie la JVM que dividen el espacio de direcciones. El uso del modificador / 3GB no reajustará esas bibliotecas, por lo que siguen siendo un problema para nosotros.

Sabemos cómo hacer montones en trozos, pero usarlos supondría algunos gastos generales. Tenemos más solicitudes para una administración de almacenamiento más rápida que para montones más grandes en la JVM de 32 bits. Si realmente desea montones grandes, cambie a la JVM de 64 bits. Todavía necesitamos memoria contigua, pero es mucho más fácil obtenerla en un espacio de direcciones de 64 bits.

Uri
fuente
Eso es muy interesante. Siempre me pregunté por qué 1500 MB, ahora lo tengo, ¡gracias!
Tim Büthe
3
Perdón por dar seguimiento a una pregunta antigua, pero esta es la mejor respuesta que he visto hasta ahora. Pero, ¿por qué falla la JVM al inicio si no puede obtener el tamaño máximo de almacenamiento dinámico? ¿No debería conformarse silenciosamente con el mejor tamaño por encima del mínimo ?
Stroboskop
19

Los límites de tamaño del montón de Java para Windows son:

  • tamaño de pila máximo posible en Java de 32 bits: 1,8 GB
  • límite de tamaño de pila recomendado en Java de 32 bits: 1,5 GB (o 1,8 GB con la opción / 3 GB)

Esto no le ayuda a obtener un montón de Java más grande, pero ahora sabe que no puede ir más allá de estos valores.

MicSim
fuente
10

Oracle JRockit , que puede manejar un montón no contiguo, puede tener un tamaño de montón de Java de 2,85 GB en Windows 2003 / XP con el modificador / 3GB. Parece que la fragmentación puede tener un gran impacto en el tamaño de un montón de Java.

Kire Haglin
fuente
6

La JVM necesita memoria contigua y, dependiendo de qué más se esté ejecutando, qué se estaba ejecutando antes y cómo Windows ha administrado la memoria, es posible que pueda obtener hasta 1,4 GB de memoria contigua. Creo que Windows de 64 bits permitirá montones más grandes.

James AN Stauffer
fuente
2
Creo que el sistema operativo moderno emula la memoria continua para. Desde el 80486, la arquitectura x86 admite la paginación para facilitar la reorganización de la memoria física.
Mnementh
3
Mnemeth: Primero, hay una API específica (AllocateUserPhysicalPages) en WINAPI para herramientas avanzadas como bases de datos y máquinas virtuales que están mejor administrando su memoria ellos mismos con Windows fuera del camino. En segundo lugar, la paginación es una función de modo protegido 80386, no 80486.
Tamas Czinege
6

La JVM de Sun necesita memoria contigua. Entonces, la cantidad máxima de memoria disponible viene dictada por la fragmentación de la memoria. Especialmente las DLL del controlador tienden a fragmentar la memoria cuando se cargan en alguna dirección base predefinida. Entonces, su hardware y sus controladores determinan cuánta memoria puede obtener.

Dos fuentes para esto con declaraciones de ingenieros de Sun: blog del foro

¿Quizás otra JVM? ¿Has probado Harmony ? Creo que planearon permitir la memoria no continua.

the.duckman
fuente
Pero pude asignar 1300 MB en una máquina con solo 1 GB de RAM (más memoria virtual). Mi máquina de 2GB RAM (también con memoria virtual) solo puede asignar 1200MB.
Steve Kuo
La armonía está muerta, ¿no?
Pacerier
Sí: "Apache Harmony está retirado de Apache Software Foundation desde el 16 de noviembre de 2011".
bobbel
3

Creo que tiene más que ver con cómo se configura Windows como se sugiere en esta respuesta: Opción Java -Xmx

Algunas pruebas más: pude asignar 1300 MB en una vieja máquina con Windows XP con solo 768 MB de RAM física (más memoria virtual). En mi máquina de 2 GB de RAM solo puedo obtener 1220 MB. En varias otras máquinas corporativas (con Windows XP más antiguo) pude obtener 1400 MB. La máquina con un límite de 1220 MB es bastante nueva (recién comprada a Dell), por lo que tal vez tenga Windows y DLL más nuevos (y más hinchados) (está ejecutando Windows XP Pro Versión 2002 SP2).

Steve Kuo
fuente
También podría verse afectado por la configuración de su memoria virtual.
skaffman
Todas las máquinas con las que pruebo tienen memoria virtual al menos el doble que la RAM física.
Steve Kuo
tenga en cuenta que realmente nunca querrá usar la memoria virtual con Java, porque el rendimiento de GC será muy malo. La cantidad de memoria depende de qué dll ya se hayan cargado y hayan fragmentado la memoria.
Kohlerm
2

Recibí este mensaje de error al ejecutar un programa Java desde un VPS virtuozzo (memoria limitada). No había especificado ningún argumento de memoria y descubrí que tenía que establecer explícitamente una pequeña cantidad, ya que el valor predeterminado debe haber sido demasiado alto. Por ejemplo, -Xmx32m (obviamente debe ajustarse en función del programa que ejecute).

Simplemente coloque esto aquí en caso de que alguien más reciba el mensaje de error anterior sin especificar una gran cantidad de memoria como lo hizo el interrogador.

William Denniss
fuente
1

El JDK / JRE de sun necesita una cantidad contigua de memoria si asigna un bloque enorme.

El sistema operativo y las aplicaciones iniciales tienden a asignar bits y piezas durante la carga, lo que fragmenta la RAM disponible. Si un bloque contiguo NO está disponible, SUN JDK no puede usarlo. JRockit de Bea (adquirido por Oracle) puede asignar memoria de piezas.

anjanb
fuente
1

Todo el mundo parece estar respondiendo sobre la memoria contigua, pero se han olvidado de reconocer un problema más urgente.

Incluso con una asignación de memoria contigua al 100%, no puede tener un tamaño de pila de 2 GiB en un sistema operativo Windows de 32 bits (* de forma predeterminada). Esto se debe a que los procesos de Windows de 32 bits no pueden abordar más de 2 GiB de espacio.

El proceso de Java contendrá perm gen (pre Java 8), tamaño de pila por hilo, sobrecarga de JVM / biblioteca (que aumenta mucho con cada compilación), todo además del montón .

Además, los indicadores de JVM y sus valores predeterminados cambian entre versiones. Simplemente ejecute lo siguiente y obtendrá una idea:

 java -XX:+PrintFlagsFinal

Muchas de las opciones afectan la división de la memoria dentro y fuera del montón. Dejándote con más o menos de esos 2 GiB para jugar ...

Para reutilizar partes de esta respuesta mía (sobre Tomcat, pero se aplica a cualquier proceso de Java):

El sistema operativo Windows limita la asignación de memoria de un proceso de 32 bits a 2 GiB en total (por defecto).

[Solo podrá] asignar alrededor de 1,5 GiB de espacio de pila porque también hay otra memoria asignada al proceso (la sobrecarga de JVM / biblioteca, espacio de generación permanente, etc.).

¿Por qué Windows de 32 bits impone un límite de espacio de direcciones de proceso de 2 GB, pero Windows de 64 bits impone un límite de 4 GB?

Otros sistemas operativos modernos [tos Linux] permiten que los procesos de 32 bits usen todo (o la mayoría) del espacio direccionable de 4 GiB.

Dicho esto, los sistemas operativos Windows de 64 bits se pueden configurar para aumentar el límite de procesos de 32 bits a 4 GiB (3 GiB en 32 bits):

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

Miguel
fuente
1
Esta respuesta solo aborda por qué es posible que solo pueda asignar 2 GB, no por qué puede asignar 1.4 GB en una computadora y solo 1.2 GB en otra. No alcanza los límites de 1,5 GB, 2 GB o 4 GB que se indican aquí.
vapcguy
1
El párrafo sobre los indicadores de JVM explica de alguna manera por qué la memoria puede variar entre versiones. Además, tenga en cuenta mi punto sobre cómo la configuración del montón es siempre una fracción (grande) del tamaño total del proceso, por lo que una configuración inferior que aún puede alcanzar el límite de proceso de 2 GiB , otra podría estar restringida por la asignación de memoria contigua.
Michael
O posiblemente el límite de 1,5 GB, en esa asignación de 1,4 GB que está haciendo. Tiene más sentido ahora, gracias por esa aclaración.
vapcguy
0

A continuación se explica cómo aumentar el tamaño de la paginación

  1. haga clic derecho en mycomputer ---> propiedades ---> Avanzado
  2. en la sección de rendimiento, haga clic en configuración
  3. haga clic en la pestaña Avanzado
  4. en la sección de memoria virtual, haga clic en cambiar. Mostrará su tamaño de paginación actual.
  5. Seleccione Unidad donde haya espacio disponible en el disco duro.
  6. Proporcione el tamaño inicial y el tamaño máximo ... por ejemplo, el tamaño inicial de 0 MB y el tamaño máximo de 4000 MB. (Tanto como necesites)
Israel Margulies
fuente
0

** Hay numerosas formas de cambiar el tamaño del montón como,

  1. file-> setting-> build, exution, deployment-> compiler aquí encontrará el tamaño del montón
  2. file-> setting-> build, exution, deployment-> compiler-> andriod aquí también encontrará el tamaño del montón. Puede referir esto para el proyecto andriod si enfrenta el mismo problema.

Lo que funcionó para mí fue

  1. Establezca la ruta JAVA_HOME adecuada en caso de que haya actualizado Java.

  2. crear nueva variable de sistema computadora-> propiedades-> configuración avanzada- > crear nueva variable de sistema

nombre: _JAVA_OPTION valor: -Xmx750m

Para su información: puede encontrar VMoption predeterminada en la ayuda de Intellij- > editar la opción de VM personalizada , en este archivo puede ver el tamaño mínimo y máximo del montón. **

Akanksha gore
fuente
-1

Primero, usar un archivo de paginación cuando tienes 4 GB de RAM es inútil. Windows no puede acceder a más de 4 GB (en realidad, menos debido a los agujeros de memoria) por lo que no se utiliza el archivo de paginación.

En segundo lugar, el espacio de direcciones se divide en 2, la mitad para el kernel y la mitad para el modo de usuario. Si necesitas más RAM para tus aplicaciones, usa la opción / 3GB en boot.ini (asegúrate de que java.exe esté marcado como "con reconocimiento de direcciones grandes" (google para más información).

En tercer lugar, creo que no puede asignar los 2 GB completos de espacio de direcciones porque Java desperdicia algo de memoria internamente (para subprocesos, compilador JIT, inicialización de VM, etc.). Utilice el conmutador / 3GB para obtener más información.

user17544
fuente
1
La idea de que un archivo de paginación sea inútil con 4GB o RAM es incorrecta. Sin un archivo de paginación, el sistema operativo no puede desalojar los datos de proceso no utilizados (espacio de pila para servicios no utilizados, etc.) de la RAM física, reduciendo así la cantidad de RAM disponible para el trabajo real. Tener un archivo de paginación libera RAM.
nadie