Administración de memoria en java

29,817 views

Published on

En esta presentación cubrimos el modelo de memoria del JDK 5/6/7, a partir de JDK 8 hay un cambio en el modelo de memoria, así que no toda la presentación seria valida, aunque algunos conceptos se mantienen.

Published in: Technology
  • de donde descargo esas clases java :'( que sugieren ejemplos
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Muchas gracias por tomarse el tiempo de compartir sus conocimientos, me gusto mucho el contenido a profundidad y la forma tan gráfica de presentarlo, facilita mucho la comprensión. Tiene mi mas sincero agradecimiento. Suerte
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Administración de memoria en java

  1. 1. Administración de memoria en Java http://javacuriosities.blogspot.com.ar/
  2. 2. Temario  ¿Qué es la memoria?  ¿Quién esta a cargo del manejo de la memoria en Java?  Áreas de memoria (Runtime Data Areas) - Stack - Heap Área - Non-Heap Área  ¿Qué pasa cuando ejecutamos nuestro programa Java?  Ciclo de vida de los objetos  Size of tipos primitivos vs Wrappers  Size of Objetos  Modelo de memoria de la JVM y sus parámetros  Garbage Collector  ¿Que es un OOM (Out Of Memory)?  ¿Qué tipos de OOM podemos encontrar? Administración de memoria en Java
  3. 3. ¿Que es la memoria? La memoria es la parte utilizada por los sistemas informáticos para almacenar información en tiempo de ejecución, o sea estamos hablando de memoria volátil, por lo cual su contenido se pierde cuando se apaga el equipo. Administración de memoria en Java
  4. 4. ¿Quién esta a cargo del manejo de la memoria en Java? La JVM (Java Virtual Machine) es la encargada de ejecutar nuestros programas Java, pero a su vez es la que esta a cargo de reservar, asignar y liberar la memoria utilizada por nuestra aplicación. La arquitectura de la JVM contiene diversas partes las cuales cumplen distintos objetivos al referirnos al manejo de memoria debemos mencionar estamos hablando del área llamada ‘Runtime Data Areas’ Administración de memoria en Java
  5. 5. Administración de memoria en Java Estructura de la JVM
  6. 6. Áreas de memoria (Runtime Data Areas) Administración de memoria en Java
  7. 7. Stack Administración de memoria en Java
  8. 8. Administración de memoria en Java Cada thread creado por la JVM posee su propio PC Register (Program Counter) y su propio Stack Frame.  Program Counter - Es el encargado de mantener un puntero a la instrucción que esta siendo ejecutada en un determinado momento por un hilo en particular, se va ir desplazando por el código.  Stack Frame - Frame: Cada método invocado crea un nuevo frame, este es usado para almacenar datos y resultados parciales, solo un frame esta activo a la vez. El frame es destruido cuando finaliza la invocación del método esta puede ser de manera normal o abrupta. - Local Variables: Cada frame contiene un array con sus propias variables locales. - Operand Stack: Cada frame contiene una pila, cuando un nuevo frame es creado este se encuentra vacío, en esta estructura se van alocando las instrucciones a ejecutar.
  9. 9. Heap Area & Non-Heap Area Administración de memoria en Java
  10. 10. Heap Area Administración de memoria en Java El Heap es el espacio de memoria en donde se almacenan las instancias de clases (Objetos) y arreglos. Esta puede crecer o ser reducida automáticamente bajo demanda. El Garbage Collector (GC) es el encargado de reclamar el espacio que los objetos van liberando. Esta área es compartida por todos los threads. Podemos identificar las siguientes dos partes  Young Generation - Eden Space: Esta es el área inicial donde se inicializan la mayoría de los objetos. - Survivor Space: En esta área se almacenan los objetos que han sobrevivido a la recolección de basura en el Eden. En general esta área esta dividida en dos partes From y To.  Old Generation - Tenured Space: Contiene los objetos que han existido por un tiempo largo y que han pasado por el Survivor space.
  11. 11. Non-Heap Area Administración de memoria en Java Esta área incluye los objetos que son considerados parte de la JVM. Al igual que el heap esta puede crecer o ser reducida automáticamente bajo demanda. Dependiendo de la implementación de la JVM el GC puede actuar sobre esta área o compactarla. Esta área es compartida por todos los threads. Podemos identificar las siguientes dos partes  Permanent Generation - Este espacio contiene todos los datos reflectivos de la JVM como por ejemplo clases y métodos. Además contiene la estructura por clase (Propiedades, Firma de métodos e implementación de métodos). Esta área además contiene dos espacios llamados Shared-RO and Shared-RW  Code Cache - Contiene la memoria usada para el código compilado por el JIT compiler y almacenado de código nativo
  12. 12. Administración de memoria en Java Runtime Constant Pool
  13. 13. From Permanent Generation To Metaspace Administración de memoria en Java Debido a que algunas implementaciones no usan este espacio y usan espacio nativo, la gente de Oracle decidió eliminar esta área y usar un nuevo llamado Metaspace. Este cambio se espera para JDK 8.  Resize automático de esta área  Algunas cosas se movieron al Heap  Nuevo flag MaxMetaspaceSize  Recolección automática al alcanzar el valor definido antes
  14. 14. Ejemplo Administración de memoria en Java  HelloWorld.java  RuntimeConstantPool.java
  15. 15. ¿Qué pasa cuando ejecutamos nuestro programa Java? Administración de memoria en Java
  16. 16. Administración de memoria en Java
  17. 17. Classloaders Administración de memoria en Java  Bootstrap Classloader carga el API básica de Java e inicia el ‘System Class Loader’.  El ‘System Classloader’ envía los archivos .class por medio de un stream binario a la JVM.  Usando ese stream la JVM obtiene la siguiente información - Constantes, literales. - Paquetes, modificadores, variables estáticas. - Información de atributos. - Información de métodos. - Referencias al Classloader y a la Clase. Esta información es almacenada en el ‘Method Area’.  Se crea el Thread-Main el cual busca el método main (Recordar que cada thread tiene su propio Stack).  El Program Counter va ejecutando el código, usando las distintas áreas de memoria.
  18. 18. Para recordar acerca de los Classloaders Administración de memoria en Java  Delegation (Delegación): El Classloader actual siempre va a delegar la tarea de carga la clase a su padre antes de intentar cargarla el mismo.  Visibility (Visibilidad): Las clases cargadas por los Classloaders padres son vistas por todos los hijos pero no de modo inverso.  Uniqueness (Unicidad): Una vez que la clase es cargada por cualquiera de sus Classloaders padres, el hijo nunca volverá a cargarla.  Configurable (Configurable): La mayoría de servidores de aplicaciones crean sus propios Classloaders utilizando como padre al System Classpath Classloader
  19. 19. Ejemplo Administración de memoria en Java  ClassLoaderDelegation.java
  20. 20. Ciclo de vida de los objetos Administración de memoria en Java  Class Loading - La primera vez que se crea un objeto de esa clase. - Cuando se accede a una propiedad o método estático de esa clase por primera vez.  Inicializadores estáticos - Inmediatamente después de cargar la clase se ejecutan los inicializadores estáticos de la clase.  Creación del objeto Un objeto es una instancia de una clase, la creación de un objeto tiene tres partes. - Declaración - Instanciación - Inicialización  Uso del objeto  Limpieza (Método Finalize y luego GC)
  21. 21. Ejemplo Administración de memoria en Java  LifeCycle.java
  22. 22. Size of tipos primitivos vs wrappers Administración de memoria en Java Primitive Type Size (Bytes) Wrapper Type Size (Bytes) char 2Character 16 byte 1Byte 16 short 2Short 16 int 4Integer 16 long 8Long 16 float 4Float 16 double 8Double 16 boolean 1Boolean 16 Como se puede observar la diferencia entre usar tipos primitivos y usar sus wrappers puede ser bastante grande.
  23. 23. Ejemplos Administración de memoria en Java  SizeOfPrimitives.java  SizeOfWrappers.java
  24. 24. Size of Objetos Administración de memoria en Java Como vimos antes los wrappers pueden consumir mucha memoria, pero lo importante es entender el porque de esto. Reglas:  Objetos: - El tamaño base de cualquier objeto es 8 bytes. - El tamaño total de un objeto siempre es múltiplo de 8 (Esto se lo conoce como padding)  Atributos: - Si el tipo del atributo es primitivo ocupa el size que le corresponde. - Si el tipo del atributo es un objeto, entonces ocupa 4 bytes porque es una referencia.  Arrays: - Array de primitivos ocupa: 8 (Base) + 4 (Length) + Length * size del tipo primitivo. - Array de objetos ocupa: 8 (Base) + 4 (Length) + Length * 4 (Size de una referencia).
  25. 25. Shallow size vs. Retained size Administración de memoria en Java Figura 1: Objeto 1: Retained size obj1, obj2, obj4 Objeto 2: Retained size obj2, obj4 Figura 2: Objeto 1: Retained size obj1, obj2, obj3, obj4 Objeto 2: Retained size obj2, obj3, obj4
  26. 26. Ejemplos Administración de memoria en Java  SizeOfObjects.java  ShallowVsRetained.java
  27. 27. Modelo de memoria de la JVM Administración de memoria en Java Debemos tener en cuenta que la máxima memoria que podemos asignar a un proceso Java va a depender del Sistema Operativo (SO) y de la JVM que estemos usando. JVM 32 bits: Valor máximo aproximado 2GB. JVM 64 bits: Valor muy superior a la de 32 bits. Aproximadamente (2^48).
  28. 28. Parámetros de memoria Administración de memoria en Java
  29. 29. Administración de memoria en Java -Xms = Mínimo tamaño del Heap. -Xmx = Máximo tamaño del Heap. -XX:NewSize = Tamaño inicial del Eden + Survivor Space. -XX:MaxNewSize / -Xmn = Máximo tamaño de Young Generation. -XX:PermSize = Mínimo tamaño del PermGen (Permanent Generation). -XX:MaxPermSize = Máximo tamaño del PermGen (Permanent Generation).
  30. 30. Parámetros JVM Administración de memoria en Java Parámetro Definicion Ejemplo -Xms Minimo tamaño del Heap -Xms512M -Xmx Maximo tamaño del Heap -Xmx512M -XX:NewSize Tamaño inicial del Eden + Survivor Space -XX:NewSize=128M -XX:MaxNewSize / -Xmn Máximo tamaño de Young Generation -XX:MaxNewSize=128M -XX:NewRatio Ratio entre Young y Old generation -XX:NewRatio=3 -XX:SurvivorRatio Ratio entre Eden y Survivor -XX:SurvivorRatio=6 -XX:PermSize Mínimo tamaño del PermGen (Permanent Generation) -XX:PermSize=64M -XX:MaxPermSize Máximo tamaño del PermGen (Permanent Generation) -XX:MaxPermSize=128M -Xss -XX:ThreadStackSize Tamaño de cada stack de cada Thread -XX:ThreadStackSize=256k -XX:MinHeapFreeRatio Indica el minimo de Heap libre antes de pedir memoria -XX:MinHeapFreeRatio=40 -XX:MaxHeapFreeRatio Indica el maximo de Heap libre antes de liberar memoria -XX:MaxHeapFreeRatio=70 -XX:TargetSurvivorRatio Indica hasta que porcentaje se puede llenar el Survivor antes de mover al Old -XX:TargetSurvivorRatio=90
  31. 31. Ejemplos Administración de memoria en Java  JVMParameters.java  MemoryViewer.java
  32. 32. Administración de memoria en Java La Recolección de basura automática es el proceso de buscar en la memoria y liberar aquellos objetos que estén disponibles para ser recolectados, podemos identificar dos tipos de objetos Reachable (Objeto sobre el cual aun hay referencias) : Significa que alguna parte de nuestro programa todavía mantiene una o mas referencias a ese objeto. Unreachable (Objeto el cual no puede ser referenciado): Ya no se hace referencia en ninguna parte del programa no hay forma de obtener la referencia a ese objeto. Así que la memoria utilizada por un objeto no referenciado puede ser reclamada. En un lenguaje de programación como C, asignar y desasignar la memoria es un proceso manual. En Java, el proceso de cancelar la asignación de memoria es manejado automáticamente por el recolector de basura. Garbage Collector
  33. 33. Garbage Collector Behaviour Administración de memoria en Java
  34. 34. Administración de memoria en Java Línea #6 Línea #8 Línea #11 System.runFinalization(): Le sugiere a la JVM a ejecutar el método finalize de los objetos que están en la cola de finalización. System.gc(): Le sugiere a la JVM ejecutar el garbage collector para reclamar espacio y liberar memoria.
  35. 35. Administración de memoria en Java Tipos de recolecciones Existen dos tipos de recolecciones  Minor GC - Ejecutado en el Young Generation, cuando el Eden se encuentra lleno o antes de incrementar el espacio de esta área se ejecuta esta recolección. Aquí se usa un algoritmo de copia.  Full GC - Ejecutado en el Tenured Generation, cuando el Old se encuentra lleno se ejecuta esta recolección o antes de incrementar el espacio de esta área. Aquí se puede usar el algoritmos MSC(Mark- Sweep- Compact) o CMS (Concurrent Mark Sweep), este ultimo no compacta los objetos luego de su ejecución lo cual genera que pedir memoria sea un poco mas complejo. Incluye el PermGen en su recolección.
  36. 36. Administración de memoria en Java Algoritmo de Copia (Paso 1)
  37. 37. Administración de memoria en Java Algoritmo de Copia (Paso 2)
  38. 38. Administración de memoria en Java Algoritmo de Copia (Paso 3)
  39. 39. Administración de memoria en Java Algoritmo de Copia (Paso 4)
  40. 40. Administración de memoria en Java Algoritmo de Copia (Paso 5)
  41. 41. Administración de memoria en Java Algoritmo de MSC (Paso 1)
  42. 42. Administración de memoria en Java Algoritmo de MSC (Paso 2)
  43. 43. Administración de memoria en Java Algoritmo de MSC (Paso 3)
  44. 44. Administración de memoria en Java Algoritmo de CMS N° Fase Descripcion 1 Initial Mark (Stop the World Event) Es una pausa pequeña donde todos los objetos "reachable" son marcados. 2Concurrent Marking Busca objetos vivos mientras la aplicación se ejecuta en otro hilos. 3 Remark (Stop the World Event) Busca los objetos que no fueron encontrados durante la parte 2. 4Concurrent Sweep Remueve los objetos que son "unreachable", es importante notar que los objetos "reachable" no son movidos, o sea no hay compactacion. 5Resetting Se prepara para la siguiente ejecución limpiando las estructuras usadas.
  45. 45. Administración de memoria en Java Tipos de GC por áreas de memoria
  46. 46. Administración de memoria en Java Young Generation:  "Serial" corre en un solo hilo y es del tipo STW (Stop-the-world).  "Parallel Scavenge" corre en múltiples hilos y aunque es del tipo STW (Stop-the-world), obtiene una mejor performance.  "ParNew" es igual que el "Parallel Scavenge" pero esta mejorado para trabajar de forma concurrente con "CMS". Tenured Generation:  "Serial Old" corre en un solo hilo y es del tipo STW, usa el algoritmo Mark-Sweep-Compact.  "Parallel Old" corre en múltiples hilos, también es del tipo STW.  "CMS" corre de forma concurrente la mayor parte del tiempo y tiene pequeñas pausas donde se ejecuta en forma STW.
  47. 47. Administración de memoria en Java
  48. 48. Administración de memoria en Java
  49. 49. Administración de memoria en Java GC Collectors JVM Young Collector Tenured Collector -XX:+UseSerialGC Serial Serial Old (MSC) -XX:+UseParNewGC ParNew Serial Old (MSC) -XX:+UseParallelGC Parallel Scavenge Serial Old (MSC) -XX:+UseParallelOldGC Parallel Scavenge Parallel Old -XX:-UseParNewGC -XX:+UseConcMarkSweepGC Serial CMS + Serial Old (MSC) -XX:+UseParNewGC -XX:+UseConcMarkSweepGC ParNew CMS + Serial Old (MSC) -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC G1
  50. 50. Administración de memoria en Java JVM Ergonomics Desde el JDK 5.0 la JDK detecta en que tipo de maquina esta y cambia su configuración, modo cliente o modo servidor. Estos cambios incluyen: - Configuración de memoria mínima y máxima para el Heap. - Selección automática del GC. - Activa el resize automático para el área Young y Tenured. - Otras configuraciones adicionales.
  51. 51. Administración de memoria en Java Analizando el GC (Parámetros) Parámetro Definicion -verbose:gc Imprime informacion por consola del GC -Xloggc:GCLogs.log Guarda la misma información que -verbose:gc en un archivo que le indiquemos pero además agrega mas detalle -XX:+PrintGCDetails Imprime el detalle de cada recoleccion -XX:+PrintGCDateStamps Imprime DateStamps para cada GC (Dia+Hora+Minutos+Segundos+Milisegundos) -XX:+PrintGCTimeStamps Imprime el TimeStamp para cada recoleccion
  52. 52. Administración de memoria en Java Analizando el GC (Revisando el output)
  53. 53. Ejemplos Administración de memoria en Java  GCMXBean.java  GCDetails.java
  54. 54. ¿Que es un OOM (Out Of Memory)? Administración de memoria en Java Este es el error que se suele producir debido a que la JVM se queda sin memoria disponible. Existen varios tipos de OOM y en base a cual de ellos nos estemos enfrentando sabremos si es porque la JVM se que sin memoria en una área o en otra.
  55. 55. Tipos de OOM Administración de memoria en Java  java.lang.OutOfMemoryError: unable to create new native thread - OOM en la memoria nativa, esta área no es controlada por nosotros sino que la maneja el SO (Sistema Operativo). Java 32-bit Native Heap = Max Process Size – Java Heap – PermGen Java 64-bit Native Heap = Memoria Fisica & Virtual – Java Heap – PermGen  java.lang.OutOfMemoryError: Java heap space - OOM en el Java Heap, esto se produce cuando tenemos demasiados objetos en memoria o tenemos un posible Memory Leak (Fuga de memoria).  java.lang.OutOfMemoryError: PermGen space - OOM en el PermGen Space, esto se produce porque estamos cargando muchas clases por nuestra aplicación, o almacenando muchos String en la cache de constantes o en servidores de aplicaciones donde intentamos desplegar la aplicación y los ClassLoader quedan referenciados.  java.langOutOfMemoryError: GC overhead limit exceeded - Este error sucede cuando el GC esta gastando mucho tiempo en limpiar la memoria y la memoria recuperada en muy poca.  java.lang.OutOfMemoryError: Requested array size exceeds VM limit - Este error sucede porque estamos intentando crear un vector mas grande que nuestro heap.
  56. 56. Ejemplos Administración de memoria en Java  OOMNativeHeap.java  OOMJavaHeapSpace.java  OOMPermGenSpace.java  OOMRequestArraySize.java
  57. 57. OOM vs Memory Leak Administración de memoria en Java No todo OOM indica una fuga de memoria (Memory Leak) - Puede haber una fuga de memoria. - La aplicación puede necesitar mas memoria.
  58. 58. Heap Dump Administración de memoria en Java Un Heap dump es una foto de la memoria de un proceso Java en un determinado momento. Dependiendo de la JVM el Heap dump puede contener una información o otra, además en general antes de ejecutar el volcado un recolección completa es ejecutada (Full GC).
  59. 59. Obteniendo un Heap Dump Administración de memoria en Java  Aplicación Externa Alguna aplicación externa como VisualVM.  HeapDumpOnOutOfMemoryError Cuando la aplicación arroje un OOM se generara un heap dump, usando el HeapDumpPath configurado.  Jmap Tool que viene incorporada en el jdk. jmap -dump:file=<file-location> <pid>  Jmap (Desde la aplicación) Podemos usar los MXBean para ejecutar el jmap desde la aplicación.  HotSpotDiagnosticMXBean(Usando Reflection) Usando el DiagnosticMXBean para hacer el dump
  60. 60. Heap Dump (Parámetros JVM) Administración de memoria en Java Parámetro Definicion Ejemplo -XX:+HeapDumpOnOutOfMemoryError Activa la generacion de un Heap Dump frente a un OOM -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath Indica el Path para el Heap Dump -XX:HeapDumpPath=C:temp
  61. 61. Ejemplo Administración de memoria en Java  MainHeapDump.java  HeapDumpPath.java
  62. 62. Analizando un Heap Dump (Puntos clave 1) Administración de memoria en Java  Revisar memoria consumida y numero de instancias. - Wrappers grandes consumidores de memoria.  Histogram - Nos muestra la cantidad de objetos por cada clase.  Analizar el Dominator Tree - Esta estructura nos muestra los objetos mas grandes, aquí debemos ver que la lista esta compuesta de lo que esperamos, en general aquí podremos ver cache no liberadas.  Group By por clase - Esta opción nos permite ver la memoria que consume cada clase, de esta forma podremos detectar objetos que se repiten varias veces y consumen un gran volumen.  Group By por value - En general para analizar si tenemos Wrappers duplicados.  Keep Unreachable objetcs - Debemos prender esta opción en el MAT para que no elimine los objetos que serian unreachables.  Object Query Language (OQL) - Lenguaje de consulta que nos deja interactuar con los objetos del Heap.
  63. 63. Analizando un Heap Dump (Puntos clave 2) Administración de memoria en Java  Revisar GC Roots - El Garbage collector recorre la memoria usando GC roots, lo cuales son porciones de memoria que pueden ser accedidas desde afuera del Heap. - Local Variables. - Thread activos. - Variables estáticas. - Referencias JNI  Shallow size vs. Retained size - Shallow size: Es el espacio ocupado por el objeto en si mismo. - Retained size: Es el espacio ocupado por el objeto en si mismo mas la suma de todos los shallow sizes que son accedidos directamente o indirectamente solo desde este objeto
  64. 64. JDK Tools Administración de memoria en Java  Jps - Nos brinda información de los procesos Java corriendo en nuestra computadora y no entrega el PID.  Jmap - Nos ofrece información de las áreas de memoria del proceso Java indicado y además nos permite generar Heap Dumps y Histogramas.  Jhat - Herramienta de análisis del Heap, es experimental y puede no estar incluida en futuras versiones.  Jstat - Nos brinda información estadística sobre el proceso Java que le indicamos, esta estadísticas incluyen tiempo del GC, JIT Compiler, Classloaders.  Jstack - Ejecuta un Thread Dump o sea un volcado de cada Thread.  Jinfo - Brinda información de configuración de un proceso Java.
  65. 65. Links Administración de memoria en Java VisualVM http://visualvm.java.net/ Memory Analyzer (MAT) http://www.eclipse.org/mat/downloads.php GCViewer https://github.com/chewiebug/GCViewer/wiki/Changelog Jprofiler http://www.ej-technologies.com/products/jprofiler/overview.html

×