JVM 32 vs 64 bits, una historia entre Netbeans y Ubuntu

Este pequeño blog no es un flame de Windows vs Linux, Eclipse vs Netbeans, OpenJDK vs SunJDK. Realmente es una rápida intro al JDK 32 bits vs JDK 64 bits.

La historia

En aquellos tiempos cuando compré la computadora desde la cual estoy escribiendo (amd64 bits, 1.5gb ram) no existían antivirus para la versión windows de 64 bits ya que era muy reciente por lo que decidí instalar minimamente windows 32 bits y trabajar así durante un tiempo, hasta que llegó el día donde windows ya iba demasiado lento, de hecho ya nisiquiera podía trabajar con "Netbeans,Kaspersky,Reproductor de música,MSN" al mismo tiempo por que el editor del IDE se ponía bastante latoso.

El día de ayer instale ubuntu 9.10 (desktop-64bits) en mi equipo y después de varias horas de configuración, algo me decía que cada que abría Netbeans (6.7.1) iba demasiado lento por alguna extraña razón, incluso más que en windowsUE (32 bits). Aquí la historia completa...

Paso 1. La instalación del JDK e IDE en Ubuntu 9.10 Desktop-64bits (La primer advertencia de que algo iba mal)

Primero a revizar la version del jdk instalada y veo que Ubuntu 9.10 tiene por defecto java-6-openjdk (64 bits)

java version "1.6.0_0"
OpenJDK Runtime Environment (IcedTea6 1.6.1) (6b16-1.6.1-1ubuntu3)
OpenJDK 64-Bit Server VM (build 14.0-b16, mixed mode)

Desinstalé el Netbeans 6.7.1 que trae por defecto ubuntu 9.10 (tiene un soporte bastante básico) y descargué Netbeans6.7.1 del sitio oficial, ahora a instalarlo y ejecutarlo por primera vez...
Mi primer impresión fué que arrancaba muy lento, incluso más que en mi viejo windowsUE lleno de porquerías y con soporte reducido para de 32bits aunque no le tomé mucha importancia pensando que era la primera vez que arrancaba el IDE...

Paso 2: Descargar los proyectos del repositorio (Empiezan los problemas simples)
Aquí solo le dije a Netbeans la ruta del comando svn, introduje la url del repositorio y checkout a los proyectos. La primer sorpresa es que al intentar hacer un checkout o commit desde Netbeans, la interfaz se quedaba congelada ... buscando el problema me entero que tiene que ver con el openjdk-6 y necesito ejecutar Netbeans con el jdk de sun para resolverlo.

Bajo el jdk de sun, lo instalo:

 apt-get install sun-java6-jdk

Ahora cambio la jvm por default:

unlink /etc/alternatives/java
ln -s /usr/lib/jvm/java-6-sun java

Paso 3: Instalando otras plataformas (Más problemas simples)
Regreso al openjdk-6 queriendo dejar todo en orden.

El proyecto que estaba configurando depende de algo llamado harness (el corazón de la plataforma Netbeans), por lo tanto tengo tengo que instalar netbeans5.5.1, lo descargo del sitio oficial y lo instalo manualmente.
Siguiente sorpresa (ya no era sorpresa, era enfado) me marca un error (no tengo el stacktrace a la mano) dónde me indica que no se puede ejecutar el wizard por un problema en la línea X. Otra vez a buscar a la red y me entero que Netbeans 5.5.1 no lanza su wizard si no lo lanzas desde un jre de sun, vaya cosa pero así es. Nuevamente cambio el JDK de sun (sun-java6-jdk) y ejecuto otra vez el wizard de instalación.
En esta ocasión no me marca error y instalo Netbeans5.5.1 y sigo adelante

Paso 4. (Comienza la frustración)
Ya saque mis proyectos del repositorio, tengo configurado todo para ejecutar proyectos RCP (Rich Client Platform) de Netbeans.
Ahora toca el turno de configurar el módulo móvil de la aplicación. Activo el soporte para JavaME con un solo click, resuelvo las dependencias del proyecto y lo ejecuto...

java.lang.UnsatisfiedLinkError: /opt/java_wireless/bin/sublime.so: /opt/java_wireless/bin/sublime.so: wrong ELF class: ELFCLASS32 (Possible cause: architecture word width mismatch)
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.jav a:1751)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java :1647)
at java.lang.Runtime.load0(Runtime.java:770)
at java.lang.System.load(System.java:1005)
at com.sun.kvem.Sublime.(Unknown Source)
at sun.reflect.NativeConstructorAccessorImpl.newInsta nce0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInsta nce(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newI nstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Construc tor.java:513)
at java.lang.Class.newInstance0(Class.java:355)
at java.lang.Class.newInstance(Class.java:30
at com.sun.kvem.Lime.createLime(Unknown Source)
at com.sun.kvem.KVMBridge.(Unknown Source)
at com.sun.kvem.KVMBridge.getBridge(Unknown Source)
at com.sun.kvem.midp.MIDP.run(Unknown Source)
at com.sun.kvem.environment.EmulatorInvoker.runEmulat orImpl(Unknown Source)
at com.sun.kvem.environment.EmulatorInvoker.main(Unkn own Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.kvem.environment.JVM.main(Unknown Source)

¿Será algun problema de permisos?, ¿Pero estoy como root, no se supone que cuando fuera el rey te iba tener contra la pared?

Nuevamente a buscar en foros y me doy cuenta que es un problema para el cual proponen soluciones demasiado costosas:
http://forums.sun.com/thread.jspa?threadID=5169915

Después de buen rato de buscar, me doy cuenta que el problema está en que el WirelessToolkit (plataforma para ejecutar aplicaciones j2me)
es únicamente compatible con versiones de 32 bits. Bueno, pues a descargar/instalar otro jdk pero ahora para la plataforma de 32bits y a cambiar la jdk default de netbeans:

	gedit gedit /usr/share/netbeans-6.7.1/etc/netbeans.conf
	netbeans_jdkhome="/usr/lib/jvm/java6-32bits" (Tienes que crear el enlace simbólico)

Ejecuto nuevamente Netbeans y ...

java.lang.UnsatisfiedLinkError: /opt/java_wireless/bin/sublime.so: /opt/java_wireless/bin/sublime.so: wrong ELF class: ELFCLASS32 (Possible cause: architecture word width mismatch)

Shit !!!

Nuevamente a buscar. Resulta que Netbeans lanza el emulador de wtk independiente de la jvm que tenga instalada, realmente lo que se tiene que hacer es modificar el script del emulador para que apunte a la jvm de 32 bits.

	gedit /usr/share/netbeans-6.7.1/mobility8/WTK2.5.2/bin/emulator
	javapathtowtk="/usr/lib/jvm/java6-32bits/bin/"

Otra vez a ejecutar la app móvil pero esta vez felizmente se abre el emulador

Paso 5. Ejecutando nuevamente el IDE (La línea entre el bien y el mal)

Una vez todo configurado (Proyectos Web,Maven,RCP,Móvil) ejecuto el proyecto pero veo que el arranque/escaneo de proyectos es muy lento (1min 20segs) y aquí empezaron mis dudas de si regresarme a windows32 bits en donde tardaba tan solo 35 segs, aquí los tiempos:

  • ubuntu 64 bits, openjdk-6-64bits: 1min 25segs
  • ubuntu 64 bits, sun-jdk-6-64bits: 1min 20segs
  • windows 32 bits, sun-jdk-6-32bits: 35 segs
  • ubuntu 64 bits, sun-jdk-6-32bits: 25segs

Todo indica que el IDE (puede ser cualquiera, IntelliJ,Eclipse,Netbeans, una app swing) se ejecuta mucho más rápido (menos de la mitad de tiempo) en una jvm de 32 bits que en una de 64 en un equipo que tiene un S.O. con soporte para 64 bits.

¿Qué? No se supone que debería ejecutarse más rápido en la jvm de 64 bits?

Java 32 bits VS Java 64 bits

Empecemos por lo que es una máquina virtual de 64 bits:
Realmente un SDK de 32 y 64 bits para un mismo sistema operativo son codificadas de manera distinta, sobre todo en la implementación nativa que toma en cuenta el espacio de direcciones.

Se puede pensar en un SDK-64 bits como otra implementación más de java, pero la principal ventaja es el largo espacio de direcciones (el doble) lo cual permite tener un heap mucho más grande (una jvm-32 bits solo puede llegar a 4gb como máximo mientras que jvm-64bits llega hasta donde tengas de memoria física) e incrementar el número máximo de threads que puede ejecutar la jvm.
¿Eso significa que el tamaño de los tipos de datos cambia entre 32 y 64 bits? No, de otra forma se perdería la portabilidad y los programas escritos en plataformas de 32 bits no correrían en las de 64 y visceversa.

La jvm tiene por así decirlo 2 sabores virtuales, el primero es una jvm lista para ejecutarse en máquinas cliente (-client) y otra tuneada para servidores (-server). La diferencia real entre ambas es que cada "sabor" utiliza diferentes compiladores que se acoplan a distintas características para mejorar el performance. El sabor server (-server) contiene un compilador adaptativo que soporta muchas de las optimizaciones de los compiladores c++ y propias como por ejemplo "aggressive inlining" para las invocaciones entre métodos.

El "sabor" cliente (-client) está optimizado para arrancar más rápido y ejecutar de mejor forma la interfaz de usuario (GUI)

El "sabor" servidor está optimizado para ejecutar procesos largos de manera más eficiente, esto se consigue realizando muchas tareas de optimización al arranque para que al ejecutar procesos se evite realizar dichas optimizaciones, por lo tanto el sabor servidor (-server) toma verdadera fuerza cuando se ejecutan aplicaciones con procesos costosos en segundo plano dentro de un servidor. De hecho, por el sabor servidor no soporta lanzar las aplicaciones con JavaWebStart, Java Plug-in ni AWT.

La gran sorpresa es que las jvm de 64 bits disponibles en este momento no permiten ejecutarse en el sabor cliente (-client), su valor por defecto y sin derecho de réplica es el sabor server. Por lo tanto cuando ejecuto mi IDE con una jvm de 64 bits le estoy dando prioridad al performance de las tareas en segundo plano y no a la GUI ni al arranque de mi IDE que realmente es lo que me intresa para programar

Conclusión

Si solo vas a programar y tienes un sistema operativo de 64 bits, muchos se irán rápidamente con la finta de ejecutar su IDE con el SDK que viene por defecto (openjdk-64 bits) pero desgraciadamente su IDE irá el doble de lento que en su viejo windows. Mi recomendación es que realmente tendrás un mejor desempeño si ejecutas tu IDE con una jvm de 32 bits por que está tuneada para ejecutar GUI's y para arrancar soberbiamente más rápido a comparación de una jvm-64 bits que le da prioridad a la ejecución de aplicaciones en un servidor y no al arranque ni a la GUI.


https://nbtapestrysupport.dev.java.net/

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

no necesariamente más rápido

No necesariamente debe ir más rápido la JVM de 64 bits. Ciertamente en un sistema operativo de 64 bits sí debería funcionar mejor, pero hablando de un IDE, puede que la parte de GUI nativa no venga en 64 bits y por eso corre tan lento... en cambio si pones todo en 32 bits ya jala igual todo...

Imagen de Grios

Información muy sustanciosa.

Solo comentar que me gustó mucho el análisis que has detallado. En lo particular, siempre habia pensado en utilizar la plataforma de Java de 64bits con la idea de rapidez en TODO. Por diversas circunstancias, siempre termino trabjajando en Windows de 32 bits.

Este post que hiciste me ha sido muy sustancioso, Muchas gracias por el tiempo invertido en explicar estos detalles tan finos.

Saludos!

Grios

Imagen de neko069

JVM...

Es bueno saber lo que mencionas, puesto que voy a mudar mi SO de 32 a 64 bits, para aprovechar el doble procesador, pero ya con esto, pues copio y pego toda mi carpeta de java tal cual esta y solo hago los enlaces simbolicos y actualizaciones de rutas donde se requiera, gracias por tu analisis...

Imagen de iberck

Se extraña una máquina

Se extraña una máquina virtual de 64 bits con el sabor cliente, si la hubiera tendría ventaja frente a la de 32 bits en cuanto a ejecución de IDE's (GUI's) se refiere.

Imagen de jali

Buen análisis

me gusto bastante como describes esto. Y si... seria muy chido tener una JVM 64bits sabor cliente ja. Aunque... en mi máquina jala muy bien netbeans (ubuntu 9.10 64 bits + 4 Gb ram)

gracias por la info

Imagen de iberck

AMD-Phenom-X4 64 bits (4gb ram)

Acabo de hacer la misma prueba en un procesador amd-phenom-x4 64 bits (4gb ram) sobre ubuntu 9.10

Tiempo en el que arranca Netbeans, abre y escanea todos mis proyectos (aprox 100 sources)
jvm64bits: 18 segs
jvm32bits: 10 segs

Jali: Intenta cambiar la jvm por una de 32 bits y mide los tiempos, lo más seguro es que mejores el rendimiento

Excelente Post

Loco MUCHAS GRACIAS por compartir tu experiencia. Yo me estoy iniciando en Linux y vengo peleando por lo mismo que vos desde hace días... La verdad que me solucionaste todo. Gracias de nuevo!

Imagen de bonfil1

Hola, justo lo que necesitaba

Que tal gracias por el post, y aprovechando el tema cusualmente estaba intentando configurar el jdk en mi ubuntu pero no e podido primero lo baje de la pagina de sun en un repositorio .bin pero me marca un erro de syntaxis el cual es el siguiente

/home/pepe/Documentos/Repositorios/java/java_ee_sdk-5_08-jdk-6u17-linux.bin: 1: Syntax error: "(" unexpected

siguiendo con eso, segui tu tutorila pero me quedo antes del paso 3 en la parte de

unlink /etc/alternatives/java
ln -s /usr/lib/jvm/java-6-sun java

por favor espero me ayudes con este de ante mano gracias y saludos a toda la comunidad java mexico

Imagen de benek

Re: Hola, justo lo que necesitaba

Para instalar la JDK en Ubuntu no tienes que descargar ningún binario manualmente, basta con instalarlo vía el árbol de paquetes APT:

$ sudo apt-get install sun-java6-jdk

Ya lo intentaste así?