2008-10-05 20 views
99

Siempre he sido capaz de asignar 1400 megabytes para Java SE que se ejecutan en Windows XP de 32 bits (Java 1.4, 1.5 y 1.6).Memoria máxima de Java en Windows XP

java -Xmx1400m ... 

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

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

por ensayo y error parece 1200 megabytes es el más 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.

+0

se daría cuenta de una diferencia en el máximo entre ejecutar la aplicación en un shell de 32 bits o un shell de 64 bits, al menos en mi experiencia, aunque los sistemas de Windows XP de 64 bits son raros. – djangofan

Respuesta

118

Tenga en cuenta que Windows tiene administración de memoria virtual y que la JVM solo necesita memoria contigua a en su espacio de direcciones. Por lo tanto, otros programas que se ejecutan en el sistema no necesariamente tienen un impacto en su tamaño de almacenamiento dinámico. 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 a través de 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á desesperado ...

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

+5

Use Process Explorer para ver dónde se están cargando las dll de memoria. A menudo, un controlador actualizado se quedará en el medio de su espacio de direcciones. Usando el comando REBASE, puede quitarlos fácilmente del camino.Sin embargo, ten en cuenta que el dll está sujeto a actualizaciones y a romper cosas. – brianegge

+2

Nunca acepté esto como una respuesta, pero stackoverflow lo marcó como respondido. –

+0

@Christopher, ¿Es posible usar JVM de 64 bits en un Windows XP de 32 bits? – Pacerier

6

La JVM necesita memoria contigua y, dependiendo de qué más esté ejecutándose, qué estaba ejecutándose anteriormente y cómo Windows ha gestionado la memoria, puede obtener hasta 1.4 GB de memoria contigua. Creo que Windows de 64 bits permitirá montones más grandes.

+2

Creo que el sistema operativo moderno emula la memoria continua para. Desde el 80486, la arquitectura x86 admite 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 ellas mismas sin Windows. En segundo lugar, la paginación es una función de modo protegido 80386, no 80486. –

1

sun's JDK/JRE 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.

3

creo que tiene más que ver con la forma en que Windows está configurado como se insinuó por esta respuesta: Java -Xmx Option

algunas pruebas más: yo era capaz de asignar 1300MB en una vieja máquina de Windows XP, con sólo 768 MB de RAM física (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).

+0

También podría verse afectada por la configuración de su memoria virtual. – skaffman

+0

Todas las máquinas que pruebo tienen memoria virtual al menos el doble de la RAM física. –

+0

tenga en cuenta que realmente nunca desea realmente utilizar la memoria virtual con java, porque el rendimiento del GC se volverá muy malo La cantidad de memoria depende de qué dll ya se haya cargado y haya fragmentado la memoria. – kohlerm

6

Sun's JVM 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 fuentes de este con las declaraciones de los ingenieros de Sun: forumblog

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

+0

Pero pude asignar 1300MB en una máquina con solo 1GB de RAM (más memoria virtual). Mi máquina RAM de 2GB (también con memoria virtual) solo puede asignar 1200MB. –

+0

Harmony está muerto ¿no? – Pacerier

+0

Sí: "Apache Harmony se retiró de la Apache Software Foundation desde el 16 de noviembre de 2011". – bobbel

49

Esto tiene que ver con la memoria contigua.

Here's some info I found online para alguien pidiendo que antes, supuestamente de un "dios VM":

The reason we need a contiguous memory region for the heap is that we have a bunch of side data structures that are indexed by (scaled) offsets from the start of the heap. For example, we track object reference updates with a "card mark array" that has one byte for each 512 bytes of heap. When we store a reference in the heap we have to mark the corresponding byte in the card mark array. We right shift the destination address of the store and use that to index the card mark array. Fun addressing arithmetic games you can't do in Java that you get to (have to :-) play in C++.

Usually we don't have trouble getting modest contiguous regions (up to about 1.5GB on Windohs, up to about 3.8GB on Solaris. YMMV.). On Windohs, the problem is mostly that there are some libraries that get loaded before the JVM starts up that break up the address space. Using the /3GB switch won't rebase those libraries, so they are still a problem for us.

We know how to make chunked heaps, but there would be some overhead to using them. We have more requests for faster storage management than we do for larger heaps in the 32-bit JVM. If you really want large heaps, switch to the 64-bit JVM. We still need contiguous memory, but it's much easier to get in a 64-bit address space.

+0

Eso es muy interesante. Siempre me pregunté por qué 1500 MB, ahora lo tengo, ¡gracias! –

+3

Lo siento por dar seguimiento a una pregunta que tiene siglos de antigüedad, pero esta es la mejor respuesta que he visto hasta ahora. ¿Pero por qué la JVM falla al inicio si no puede obtener el tamaño de pila máximo? ¿No debería conformarse silenciosamente con el mejor tamaño arriba _minimum_? – Stroboskop

+0

Enlace inactivo ........... – Pacerier

19

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

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

Esto no le ayuda a conseguir un mayor almacenamiento dinámico de Java, pero ahora se sabe que no puede ir más allá de estos valores.

10

Oracle JRockit, que puede manejar un montón no contiguo, puede tener un tamaño de almacenamiento dinámico 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.

-1

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).

Tercero, creo que no se puede asigna los 2 GB completos de espacio de direcciones porque java desperdicia algo de memoria internamente (para hilos, compilador JIT, inicialización de VM, etc.). Usa el modificador/3GB para obtener más.

+1

La idea de que un archivo de página sea inútil con 4 GB 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. –

2

Recibí este mensaje de error al ejecutar un programa java desde a (memoria limitada) virtuozzo VPS. No había especificado ningún argumento de memoria, y encontré que tenía que establecer explícitamente un pequeña cantidad ya que el valor predeterminado debe haber sido demasiado alto. Por ejemplo, -Xmx32m (obviamente, debe ajustarse según el programa se ejecuta).

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.

0

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

  1. haga clic derecho en Mi PC ---> propiedades ---> Avanzado
  2. en la sección de rendimiento Haga clic en Configuración
  3. clic pestaña Avanzado
  4. en la sección Memoria virtual, haga clic en cambiar. Mostrará su tamaño actual de paginación .
  5. Seleccione Unidad donde hay espacio en disco duro disponible.
  6. Proporcione el tamaño inicial y el tamaño máximo ... p. Ej. tamaño inicial 0 MB y tamaño máximo 4000 MB. (Tanto como sea necesario)
1

Parece que todo el mundo está respondiendo sobre la memoria contigua, pero se han olvidado de reconocer un problema más apremiante.

Incluso con una asignación de memoria 100% contigua, no puede tener un tamaño de almacenamiento dinámico 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 subproceso, JVM/sobrecarga de biblioteca (que aumenta con cada compilación) todo además del montón.

Además, las marcas de JVM y sus valores predeterminados cambian de una versión a otra. Simplemente ejecute el siguiente y obtendrá una idea:

java -XX:+PrintFlagsFinal 

Las porciones de las opciones afectan división de memoria dentro y fuera del montón. dejándole con más o menos de ese 2 GiB para jugar con ...

Para volver a utilizar partes de this respuesta mío (alrededor de Tomcat, pero se aplica a cualquier proceso de Java):

The Windows OS limits the memory allocation of a 32-bit process to 2 GiB in total (by default).

[You will only be able] to allocate around 1.5 GiB heap space because there is also other memory allocated to the process (the JVM/library overhead, perm gen space etc.).

Why does 32-bit Windows impose a 2 GB process address space limit, but 64-bit Windows impose a 4GB limit?

Other modern operating systems [cough Linux] allow 32-bit processes to use all (or most) of the 4 GiB addressable space.

That said, 64-bit Windows OS's can be configured to increase the limit of 32-bit processes to 4 GiB (3 GiB on 32-bit):

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

+0

Esta respuesta solo aborda por qué solo podría asignar 2 GB, no por qué puede asignar 1,4 GB en una computadora y solo 1,2 GB en otra. No acierta los límites de 1,5 GB, 2 GB o 4 GB que se indican aquí. – vapcguy

+1

El párrafo sobre indicadores de JVM explica de alguna manera por qué la memoria puede variar entre versiones. Además, tenga en cuenta mi punto acerca de cómo la configuración de almacenamiento dinámico 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 2 GiB _process_, otra puede estar restringida por la asignación de memoria contigua. – Mikaveli

+0

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

Cuestiones relacionadas