Este artículo se centrará en la gestión de la memoria de Java, cómo funciona el almacenamiento dinámico, los tipos de referencia, la recolección de elementos no utilizados y también los conceptos relacionados.
¿Por qué aprender la gestión de memoria de Java?
Todos sabemos que el propio Java gestiona la memoria y no necesita la intervención explícita del programador. El propio recolector de basura garantiza que el espacio no utilizado se limpie y la memoria se pueda liberar cuando no se necesite. Entonces, ¿cuál es el papel del programador y por qué un programador necesita aprender sobre la gestión de memoria de Java? Siendo un programador, no necesitas preocuparte por problemas como destruir objetos, todos los créditos para el recolector de basura. Sin embargo, la recolección automática de basura no garantiza todo. Si no sabemos cómo funciona la administración de la memoria, a menudo terminaremos en medio de cosas que no son administradas por JVM (Java Virtual Machine). Hay algunos objetos que no son elegibles para la recolección automática de elementos no utilizados.
Por lo tanto, conocer la gestión de la memoria es esencial, ya que beneficiará al programador para escribir programas de alto rendimiento que no se bloqueen o, si lo hace, el programador sabrá cómo depurar o superar los bloqueos.
Introducción:
En todos los lenguajes de programación, la memoria es un recurso vital y también es escaso por naturaleza. Por lo tanto, es esencial que la memoria se administre a fondo sin fugas. La asignación y desasignación de memoria es una tarea crítica y requiere mucho cuidado y consideración. Sin embargo, en Java, a diferencia de otros lenguajes de programación, JVM y, para ser específicos, Garbage Collector tiene la función de administrar la asignación de memoria para que el programador no tenga que hacerlo. Mientras que en otros lenguajes de programación como C, el programador tiene acceso directo a la memoria que asigna memoria en su código, lo que crea muchas posibilidades de fugas.
Los principales conceptos en Java Memory Management:
- Estructura de memoria JVM
- Funcionamiento del recolector de basura
Estructura de memoria de Java:
JVM define varias áreas de datos de tiempo de ejecución que se utilizan durante la ejecución de un programa. Algunas de las áreas son creadas por la JVM, mientras que otras son creadas por los subprocesos que se utilizan en un programa. Sin embargo, el área de memoria creada por JVM se destruye solo cuando se cierra la JVM. Las áreas de datos del subproceso se crean durante la creación de instancias y se destruyen cuando el subproceso sale.
Estudiemos estas partes del área de la memoria en detalle:
Montón :
- Es un área de datos de tiempo de ejecución compartida y almacena el objeto real en una memoria. Se crea una instancia durante el inicio de la máquina virtual.
- Esta memoria se asigna para todas las instancias de clase y array. El almacenamiento dinámico puede tener un tamaño fijo o dinámico según la configuración del sistema.
- JVM proporciona el control del usuario para inicializar o variar el tamaño del montón según el requisito. Cuando se usa una nueva palabra clave, se le asigna un espacio al objeto en el montón, pero la referencia del mismo existe en la pila.
- Existe un único montón para un proceso JVM en ejecución.
Escáner sc = nuevo Escáner (System.in);
La declaración anterior crea el objeto de la clase Scanner que se asigna al montón, mientras que la referencia ‘sc’ se empuja a la pila.
Nota: La recolección de basura en el área del montón es obligatoria.
Área de método:
- Es una parte lógica del área de almacenamiento dinámico y se crea al iniciar la máquina virtual.
- Esta memoria se asigna para estructuras de clase, datos de métodos y datos de campos de constructores, y también para interfaces o métodos especiales utilizados en clase. El almacenamiento dinámico puede tener un tamaño fijo o dinámico según la configuración del sistema.
- Puede tener un tamaño fijo o expandirse según lo requiera el cálculo. No necesita ser contiguo.
Nota: Aunque el área de método es lógicamente una parte del montón, puede o no ser basura recolectada incluso si la recolección de basura es obligatoria en el área del montón.
Pilas de JVM:
- Se crea una pila al mismo tiempo que se crea un subproceso y se utiliza para almacenar datos y resultados parciales que se necesitarán al devolver el valor para el método y realizar la vinculación dinámica.
- Las pilas pueden ser de tamaño fijo o dinámico. El tamaño de una pila se puede elegir de forma independiente cuando se crea.
- La memoria para la pila no necesita ser contigua.
Pilas de métodos nativos:
También llamadas pilas C, las pilas de métodos nativos no están escritas en lenguaje Java. Esta memoria se asigna para cada subproceso cuando se crea. Y puede ser de naturaleza fija o dinámica.
Registros del contador de programa (PC):
Cada subproceso de JVM que lleva a cabo la tarea de un método específico tiene un registro de contador de programa asociado. El método no nativo tiene una PC que almacena la dirección de la instrucción JVM disponible, mientras que en un método nativo, el valor del contador del programa no está definido. El registro de PC es capaz de almacenar la dirección de retorno o un puntero nativo en alguna plataforma específica.
Funcionamiento de un recolector de basura:
- JVM desenstring este proceso y, según el proceso de recolección de basura de JVM, se realiza o se retiene. Reduce la carga del programador al realizar automáticamente la asignación o desasignación de memoria.
- El proceso de recolección de elementos no utilizados hace que el resto de los procesos o subprocesos se detengan y, por lo tanto, es de naturaleza costosa. Este problema es inaceptable para el cliente, pero se puede eliminar aplicando varios algoritmos basados en el recolector de basura. Este proceso de aplicación de algoritmos a menudo se denomina ajuste de Garbage Collector y es importante para mejorar el rendimiento de un programa.
- Otra solución son los recolectores de basura generacionales que agregan un campo de edad a los objetos a los que se les asigna una memoria. A medida que se crean más y más objetos, la lista de basura crece, lo que aumenta el tiempo de recolección de basura. Sobre la base de cuántos ciclos de reloj han sobrevivido los objetos, los objetos se agrupan y se les asigna una «edad» en consecuencia. De esta manera se distribuye el trabajo de recolección de basura.
- En el escenario actual, todos los recolectores de basura son generacionales y, por lo tanto, óptimos.
Nota: System.gc() y Runtime.gc() son los métodos que solicitan explícitamente la recolección de basura a JVM, pero no garantizan la recolección de basura ya que la decisión final de la recolección de basura es solo de JVM.
Saber cómo se almacena u organiza el programa y sus datos es esencial ya que ayuda cuando el programador pretende escribir un código optimizado en términos de recursos y su consumo. También ayuda a encontrar pérdidas de memoria o inconsistencias, y ayuda a depurar errores relacionados con la memoria. Sin embargo, el concepto de gestión de memoria es extremadamente amplio y, por lo tanto, uno debe esforzarse por estudiarlo lo más posible para mejorar el conocimiento de la misma.
Publicación traducida automáticamente
Artículo escrito por theprogrammedwords y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA