La pregunta no es sobre el tamaño máximo del montón en un sistema operativo de 32 bits, dado que los sistemas operativos de 32 bits tienen un tamaño máximo de memoria direccionable de 4 GB, y que el tamaño máximo del montón de la JVM depende de cuánta memoria libre contigua se puede reservar.
Estoy más interesado en conocer el tamaño de pila máximo (tanto teórico como prácticamente alcanzable) para una JVM de 32 bits que se ejecuta en un sistema operativo de 64 bits. Básicamente, estoy buscando respuestas similares a las cifras en una pregunta relacionada sobre SO .
En cuanto a por qué se usa una JVM de 32 bits en lugar de una de 64 bits, la razón no es técnica, sino administrativa / burocrática; probablemente sea demasiado tarde para instalar una JVM de 64 bits en el entorno de producción.
Puede preguntar al Java Runtime:
Esto informará la "memoria máxima" según la asignación de montón predeterminada. Así que aún necesitarías jugar con
-Xmx
(en HotSpot ). Descubrí que al ejecutar Windows 7 Enterprise de 64 bits, mi JVM HotSpot de 32 bits puede asignar hasta 1577MiB:Mientras que con una JVM de 64 bits en el mismo sistema operativo, por supuesto, es mucho más alta (alrededor de 3TiB)
Como ya han mencionado otros, depende del sistema operativo.
Para un sistema operativo host de 64 bits, si la JVM es de 32 bits, seguirá dependiendo, probablemente como se muestra arriba.
- ACTUALIZACIÓN 20110905 : solo quería señalar algunas otras observaciones / detalles:
Runtime.MaxMemory
que se puede asignar también depende del conjunto de trabajo del sistema operativo . Una vez ejecuté esto mientras también tenía VirtualBox en ejecución y descubrí que no podía iniciar con éxito HotSpot JVM-Xmx1590M
y tenía que reducirlo. Esto también implica que puede obtener más de 1590M dependiendo del tamaño de su conjunto de trabajo en ese momento (aunque todavía mantengo que estará por debajo de 2GiB para 32 bits debido al diseño de Windows)fuente
No especifica qué sistema operativo.
En Windows (para mi aplicación, una aplicación de gestión de riesgos de larga duración) observamos que no podíamos ir más allá de 1280 MB en Windows de 32 bits. Dudo que ejecutar una JVM de 32 bits por debajo de 64 bits haga alguna diferencia.
Portamos la aplicación a Linux y estamos ejecutando una JVM de 32 bits en hardware de 64 bits y hemos tenido una VM de 2,2 GB funcionando con bastante facilidad.
El mayor problema que puede tener es GC, dependiendo de para qué esté usando la memoria.
fuente
Desde 4.1.2 Tamaño del montón :
Encontré una respuesta bastante buena aquí: memoria máxima de Java en Windows XP .
fuente
Recientemente hemos tenido alguna experiencia con esto. Recientemente, hemos portado de Solaris (x86-64 Versión 5.10) a Linux (RedHat x86-64) y nos hemos dado cuenta de que tenemos menos memoria disponible para un proceso JVM de 32 bits en Linux que Solaris.
Para Solaris, esto casi llega a 4 GB (http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#gc_heap_32bit).
Ejecutamos nuestra aplicación con -Xms2560m -Xmx2560m -XX: MaxPermSize = 512m -XX: PermSize = 512m sin problemas en Solaris durante los últimos años. Intenté moverlo a Linux y tuvimos problemas con errores aleatorios de memoria insuficiente al iniciar. Solo pudimos hacer que se iniciara de manera consistente en -Xms2300 -Xmx2300 . Luego, el soporte nos informó de esto.
fuente
Las limitaciones de una JVM de 32 bits en un sistema operativo de 64 bits serán exactamente las mismas que las limitaciones de una JVM de 32 bits en un sistema operativo de 32 bits. Después de todo, la JVM de 32 bits se ejecutará en una máquina virtual de 32 bits (en el sentido de virtualización) por lo que no sabrá que se está ejecutando en un sistema operativo / máquina de 64 bits.
La única ventaja de ejecutar una JVM de 32 bits en un sistema operativo de 64 bits frente a un sistema operativo de 32 bits es que puede tener más memoria física y, por lo tanto, encontrará cambios / paginación con menos frecuencia. Sin embargo, esta ventaja solo se realiza plenamente cuando tiene varios procesos.
fuente
Cuando trabajaba para BEA, descubrimos que la aplicación promedio en realidad funcionaba más lentamente en una JVM de 64 bits, que cuando se ejecutaba en una JVM de 32 bits. En algunos casos, el impacto en el rendimiento fue hasta un 25% más lento. Por lo tanto, a menos que su aplicación realmente necesite toda esa memoria adicional, sería mejor que configurara más servidores de 32 bits.
Según recuerdo, las tres justificaciones técnicas más comunes para el uso de 64 bits con las que se encontró el personal de servicios profesionales de BEA fueron:
.
fuente
JROCKIT JVM actualmente propiedad de Oracle admite el uso de almacenamiento dinámico no contiguo, lo que permite que la JVM de 32 bits acceda a más de 3,8 GB de memoria cuando la JVM se ejecuta en un sistema operativo Windows de 64 bits. (2,8 GB cuando se ejecuta en un sistema operativo de 32 bits).
http://blogs.oracle.com/jrockit/entry/how_to_get_almost_3_gb_heap_on_windows
La JVM se puede descargar libremente (se requiere registro) en
http://www.oracle.com/technetwork/middleware/jrockit/downloads/index.html
fuente
Aquí hay algunas pruebas en Solaris y Linux de 64 bits
Solaris 10 - SPARC - Máquina T5220 con 32 GB de RAM (y aproximadamente 9 GB libres)
Por cierto: aparentemente Java no asigna mucha memoria real con el inicio. Parecía tomar solo unos 100 MB por instancia iniciada (comencé 10)
Solaris 10 - x86 - VMWare VM con 8 GB de RAM (aproximadamente 3 GB libres *)
Los 3 GB de RAM libre no son realmente ciertos. Hay una gran cantidad de RAM que usan las cachés de ZFS, pero no tengo acceso de root para verificar cuánto exactamente
RedHat 5.5 - x86 - VMWare VM con 4 GB de RAM (aproximadamente 3.8 GB usados - 200 MB en búferes y 3.1 GB en cachés, por lo que aproximadamente 3 GB libres)
Misma máquina usando JRE 7
fuente
Debería ser mucho mejor
Para una JVM de 32 bits que se ejecuta en un host de 64 bits, imagino que lo que queda para el montón será cualquier espacio virtual no fragmentado que esté disponible después de la JVM, sus propias DLL y cualquier material de compatibilidad del sistema operativo de 32 bits que se haya cargado. Como una suposición salvaje, pensaría que 3GB deberían ser posibles, pero cuánto mejor eso depende de qué tan bien lo esté haciendo en 32-bit-host-land.
Además, incluso si pudiera hacer un montón gigante de 3 GB, es posible que no desee hacerlo, ya que esto hará que las pausas de GC se vuelvan potencialmente problemáticas. Algunas personas simplemente ejecutan más JVM para usar la memoria adicional en lugar de una gigante. Me imagino que están ajustando las JVM en este momento para que funcionen mejor con montones gigantes.
Es un poco difícil saber exactamente cuánto mejor puede hacer. Supongo que su situación de 32 bits se puede determinar fácilmente mediante un experimento. Ciertamente es difícil de predecir de manera abstracta, ya que muchas cosas influyen en ello, particularmente porque el espacio virtual disponible en hosts de 32 bits está bastante restringido. El montón debe existir en la memoria virtual contigua, por lo que la fragmentación del espacio de direcciones para dll y el uso interno del espacio de direcciones por parte del kernel del sistema operativo determinará el rango de posibles asignaciones.
El SO utilizará parte del espacio de direcciones para mapear dispositivos HW y sus propias asignaciones dinámicas. Si bien esta memoria no está asignada al espacio de direcciones del proceso de Java, el kernel del sistema operativo no puede acceder a ella y a su espacio de direcciones al mismo tiempo, por lo que limitará el tamaño del espacio virtual de cualquier programa.
La carga de DLL depende de la implementación y el lanzamiento de la JVM. La carga del kernel del sistema operativo depende de una gran cantidad de cosas, el lanzamiento, el HW, cuántas cosas ha mapeado hasta ahora desde el último reinicio, quién sabe ...
En resumen
Apuesto a que obtienes 1-2 GB en tierra de 32 bits y aproximadamente 3 en 64 bits, por lo que una mejora general de aproximadamente el doble .
fuente
En Solaris, el límite ha sido de aproximadamente 3,5 GB desde Solaris 2.5. (hace unos 10 años)
fuente
Tenía los mismos problemas con la JVM que usa App Inventor para Android Blocks Editor. Establece el montón en 925 m como máximo. Esto no es suficiente, pero no pude configurarlo a más de 1200 m, dependiendo de varios factores aleatorios en mi máquina.
Descargué Nightly, el navegador beta de 64 bits de Firefox, y también la versión JAVA 7 de 64 bits.
Todavía no he encontrado mi nuevo límite de almacenamiento dinámico, pero acabo de abrir una JVM con un tamaño de almacenamiento dinámico de 5900 m . ¡No hay problema!
Estoy ejecutando Win 7 64 bit Ultimate en una máquina con 24 GB de RAM.
fuente
Intenté configurar el tamaño del montón hasta 2200M en una máquina Linux de 32 bits y JVM funcionó bien. La JVM no se inició cuando la configuré en 2300M.
fuente
Este es un ajuste pesado, pero puede obtener un montón de 3 GB.
http://www.microsofttranslator.com/bv.aspx?from=&to=en&a=http://forall.ru-board.com/egor23/online/FAQ/Virtual_Memory/Limits_Virtual_Memory.html
fuente
un punto más aquí para JVM hotspot de 32 bits: - la capacidad del montón nativo = 4 Gig - Java Heap - PermGen;
Puede resultar especialmente complicado para JVM de 32 bits, ya que Java Heap y el Heap nativo están en una carrera. Cuanto más grande sea su Java Heap, más pequeño será el Heap nativo. Intentar configurar un montón grande para una máquina virtual de 32 bits, por ejemplo, .2.5 GB + aumenta el riesgo de OutOfMemoryError nativo dependiendo de la huella de su aplicación, número de subprocesos, etc.
fuente
La limitación también proviene del hecho de que, para una
32 bit
máquina virtual, laheap
misma tiene que comenzar en la dirección cero si desea todos esos4GB
.Piense en ello, si desea hacer referencia a algo a través de:
es decir, una referencia que tiene esta representación de bits en particular, significa que está intentando acceder a la primera memoria del montón. Para que eso sea posible, el montón debe comenzar en la dirección cero. Pero eso nunca sucede, comienza en algún desplazamiento desde cero:
Debido a que el montón nunca comienza desde la dirección cero en un
OS
, hay bastantes bits que nunca se utilizan desde una32
referencia de bits y, por lo tanto, el montón al que se puede hacer referencia es menor.fuente
4gb teórico, pero en la práctica (para IBM JVM):
Win 2k8 64, IBM Websphere Application Server 8.5.5 de 32 bits
C:\IBM\WebSphere\AppServer\bin>managesdk.bat -listAvailable -verbose CWSDK1003I: Доступные SDK: CWSDK1005I: Имя SDK: 1.6_32 - com.ibm.websphere.sdk.version.1.6_32=1.6 - com.ibm.websphere.sdk.bits.1.6_32=32 - com.ibm.websphere.sdk.location.1.6_32=${WAS_INSTALL_ROOT}/java - com.ibm.websphere.sdk.platform.1.6_32=windows - com.ibm.websphere.sdk.architecture.1.6_32=x86_32 - com.ibm.websphere.sdk.nativeLibPath.1.6_32=${WAS_INSTALL_ROOT}/lib/native/win /x86_32/ CWSDK1001I: Задача managesdk выполнена успешно. C:\IBM\WebSphere\AppServer\java\bin>java -Xmx2036 MaxMemory JVMJ9GC017E -Xmx слишком мала, должна быть не меньше 1 M байт JVMJ9VM015W Ошибка инициализации для библиотеки j9gc26(2): Не удалось инициализи ровать Could not create the Java virtual machine. C:\IBM\WebSphere\AppServer\java\bin>java -Xmx2047M MaxMemory Total Memory: 4194304 (4.0 MiB) Max Memory: 2146435072 (2047.0 MiB) Free Memory: 3064536 (2.9225692749023438 MiB) C:\IBM\WebSphere\AppServer\java\bin>java -Xmx2048M MaxMemory JVMJ9VM015W Ошибка инициализации для библиотеки j9gc26(2): Не удалось создать эк земпляр кучи; запрошено 2G Could not create the Java virtual machine.
RHEL 6.4 64, IBM Websphere Application Server 8.5.5 32 bits
[bin]./java -Xmx3791M MaxMemory Total Memory: 4194304 (4.0 MiB) Max Memory: 3975151616 (3791.0 MiB) Free Memory: 3232992 (3.083221435546875 MiB) [root@nagios1p bin]# ./java -Xmx3793M MaxMemory Total Memory: 4194304 (4.0 MiB) Max Memory: 3977248768 (3793.0 MiB) Free Memory: 3232992 (3.083221435546875 MiB) [bin]# /opt/IBM/WebSphere/AppServer/bin/managesdk.sh -listAvailable -verbose CWSDK1003I: Available SDKs : CWSDK1005I: SDK name: 1.6_32 - com.ibm.websphere.sdk.version.1.6_32=1.6 - com.ibm.websphere.sdk.bits.1.6_32=32 - com.ibm.websphere.sdk.location.1.6_32=${WAS_INSTALL_ROOT}/java - com.ibm.websphere.sdk.platform.1.6_32=linux - com.ibm.websphere.sdk.architecture.1.6_32=x86_32 -com.ibm.websphere.sdk.nativeLibPath.1.6_32=${WAS_INSTALL_ROOT}/lib/native/linux/x86_32/ CWSDK1001I: Successfully performed the requested managesdk task.
fuente