Memoria máxima de Java en Windows XP

Siempre he podido asignar 1400 megabytes para Java SE ejecutándose 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 a 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.

Tenga en cuenta que Windows tiene administración de memoria virtual y que la JVM solo necesita memoria contigua en su espacio de direcciones . Por lo tanto, otros progtwigs que se ejecutan en el sistema no necesariamente tienen un impacto en su tamaño de almacenamiento dynamic. Lo que se interpondrá en su camino son las DLL que se cargan en su espacio de direcciones. Lamentablemente, las optimizaciones en Windows que minimizan la reubicación de las DLL durante la vinculación hacen que sea más probable que tenga un espacio de direcciones fragmentado. Las cosas que probablemente incluirán en su espacio de direcciones aparte de las habituales incluyen software de seguridad, software CBT, spyware 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 2GB del espacio de 4GB de 32 bits).

Podría intentar examinar los enlaces de DLL en su proceso de JVM y tratar de volver a establecer la base de sus DLL en un espacio de direcciones más compacto. No es divertido, pero si estás desesperado …

Alternativamente, puede cambiar a Windows de 64 bits y una JVM de 64 bits. A pesar de lo que otros han sugerido, a pesar de que masticará más RAM, tendrá mucho más espacio de direcciones virtuales contiguas, y la asignación contigua de 2 GB sería trivial.

Esto tiene que ver con la memoria contigua.

Aquí hay alguna información que encontré en línea para alguien que pregunta 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 conjunto de estructuras de datos secundarias que están indexadas por compensaciones (a escala) desde el inicio del almacenamiento dynamic. Por ejemplo, rastreamos las actualizaciones de referencia de objetos con una “matriz de marca de tarjeta” que tiene un byte por cada 512 bytes de stack. Cuando almacenamos una referencia en el montón, tenemos que marcar el byte correspondiente en la matriz de marca de tarjeta. Nos desplazamos a la derecha la dirección de destino de la tienda y la usamos para indexar la matriz de marca de tarjeta. Divertidos juegos aritméticos de direccionamiento que no puedes hacer en Java que tienes (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 la JVM se inicie y rompan el espacio de direcciones. Usar el modificador / 3GB no volverá a establecer una base de esas bibliotecas, por lo que siguen siendo un problema para nosotros.

Sabemos cómo hacer montones fragmentados, pero habría algunos gastos generales para usarlos. Tenemos más solicitudes para una administración de almacenamiento más rápida que para acumulaciones 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 acceder a un espacio de direcciones de 64 bits.

Los límites de tamaño de almacenamiento Java para Windows son:

  • máximo tamaño de almacenamiento dynamic posible en Java de 32 bits: 1,8 GB
  • Límite de tamaño de stack recomendado en Java de 32 bits: 1.5 GB (o 1.8 GB con la opción de 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.

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

La JVM necesita memoria contigua y, en función de qué más se está ejecutando, qué se estaba ejecutando anteriormente y cómo Windows ha gestionado 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.

La JVM de Sun necesita memoria contigua. Por lo tanto, la cantidad máxima de memoria disponible está dictada por la fragmentación de la memoria. Especialmente dlls del controlador tienden a fragmentar la memoria, al cargar en una dirección base predefinida. Entonces, su hardware y sus controladores determinan cuánta memoria puede obtener.

Dos fonts para esto con declaraciones de los ingenieros de Sun: foro blog

Tal vez otra JVM? ¿Has probado Harmony ? Creo que planearon permitir la memoria no continua.

Creo que tiene más que ver con la forma en que Windows está configurado como insinuado por esta respuesta: Opción Java -Xmx

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

Recibí este mensaje de error cuando ejecuté un progtwig java desde un VPS Virtuozzo (memoria limitada). No había especificado ningún argumento de memoria, y encontré que tenía que establecer explícitamente una cantidad pequeña ya que el valor predeterminado debe haber sido demasiado alto. Ej. -Xmx32m (obviamente, debe ajustarse según el progtwig que ejecute).

Simplemente poniendo 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.

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

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

Todos parecen estar respondiendo sobre la memoria contigua, pero han olvidado reconocer un problema más apremiante.

Incluso con una asignación de memoria 100% contigua, no puede tener un tamaño de almacenamiento dynamic 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), el tamaño de la stack por subproceso, JVM / overhead de la biblioteca (que prácticamente aumenta con cada comstackción), además del montón .

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

  java -XX:+PrintFlagsFinal 

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

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 (de forma predeterminada).

[Solo podrá] asignar alrededor de 1,5 espacio de almacenamiento dynamic de GiB porque también hay otra memoria asignada al proceso (la sobrecarga de la JVM / biblioteca, el espacio generador de perm, 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 todos (o la mayoría) del espacio direccionable de 4 GiB.

Dicho esto, el sistema operativo Windows de 64 bits se puede configurar para boost el límite de los 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

Aquí es cómo boost el tamaño de paginación

  1. haga clic derecho en mycomputer —> propiedades —> Avanzado
  2. en la sección de rendimiento, haga clic en configuración
  3. clic en la pestaña Avanzado
  4. en la sección Memoria virtual, haga clic en cambiar. Mostrará tu tamaño actual de paginación.
  5. Seleccione Unidad donde el espacio HDD está disponible.
  6. Proporcione el tamaño inicial y el tamaño máximo … por ejemplo, tamaño inicial de 0 MB y tamaño máximo de 4000 MB. (Tanto como lo requiera)

Primero, usar un archivo de página 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 el archivo de página no se utiliza.

En segundo lugar, el espacio de direcciones se divide en 2, la mitad para el núcleo, la mitad para el modo de usuario. Si necesita más RAM para sus aplicaciones, use la opción / 3GB en boot.ini (asegúrese de que java.exe esté marcado como “gran dirección consciente” (google para obtener 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 hilos, comstackdor JIT, inicialización de VM, etc.). Use el interruptor / 3GB para más.