En Java, su gestión de memoria incluye dos aspectos: asignación de memoria (al crear objetos Java) y reciclaje de memoria. Ambos aspectos del trabajo se completan automáticamente mediante el JVM, reduciendo la dificultad de aprender para los programadores de Java y evitar el peligro de operar directamente la memoria como C/C ++. Sin embargo, es precisamente porque la gestión de la memoria es manejada por completo por el JVM que a muchos programadores de Java ya no se preocupan por la asignación de memoria, lo que resulta en que muchos programas son ineficientes y consumidores de memoria. Por lo tanto, los programadores de Java deben comprender el JVM al final para escribir programas más eficientes y hacer un uso completo de la memoria limitada.
1. Estado de Java en la memoria
Primero, escribamos un código como ejemplo:
Persona.java
prueba de paquete; import java.io.serializable; la persona de clase pública implementa serializable {static final long serialversionUid = 1l; Nombre de cadena; // nombra a la persona amiga; // Friends Public Person () {} Public Person (nombre de cadena) {super (); this.name = name; }} Test.java
prueba de paquete; prueba de clase pública {public static void main (string [] args) {persona p1 = nueva persona ("kevin"); Persona p2 = nueva persona ("lluvia"); Persona p3 = nueva persona ("soleado"); p1.friend = P2; P3 = P2; p2 = nulo; }} Si dibuja la referencia del objeto en el aspecto principal en Test.java anterior en un diagrama de referencia de objeto que comienza desde el método principal, es así (los vértices son objetos y referencias, y los bordes dirigidos son relaciones de referencia):
Cuando el programa se ejecuta, después de que se considera un gráfico dirigido, se puede dividir en tres tipos:
1) Estado alcanzable: después de que se crea un objeto, más de una variable de referencia se refiere a él. En un gráfico dirigido, puede navegar al objeto desde el vértice inicial, y está en un estado accesible.
2) Estado recuperable: si un objeto en el programa ya no tiene ninguna variable de referencia que se refiera a él, primero ingresará el estado restaurable, y en este momento no puede navegar al objeto desde el vértice inicial del gráfico dirigido. En este estado, el mecanismo de recolección de basura del sistema está listo para reciclar la memoria ocupada por el objeto. Antes de reciclar, el sistema llamará al método Finalize () para limpiar el recurso. Si se recupera más de una variable de referencia después de ordenar el recurso, el objeto se convertirá nuevamente en un estado accesible; de lo contrario, ingresará a un estado inalcanzable.
3) Estado inalcanzable: cuando todas las asociaciones del objeto se cortan y el sistema llama al método Finalize () para limpiar el recurso aún no hace que el estado del objeto sea accesible, entonces el objeto perderá referencia permanentemente y se convertirá en un estado inalámbrico, y el sistema realmente reciclará los recursos ocupados por el objeto.
El diagrama de transición de los tres estados anteriores es el siguiente:
2. 4 Referencias a objetos de Java
1) referencia fuerte: cree un objeto y asigne este objeto directamente a una variable, por ejemplo: persona persona = nueva persona ("soleado"); No importa cuán ajustados sean los recursos del sistema, el objeto referenciado fuerte nunca se reciclará, incluso si no se volverá a utilizar en el futuro.
2) Referencia suave: implementada a través de la clase Softreference, por ejemplo: Softreference <Oll> P = New Softreference <Oller> (nueva persona ("lluvia")); cuando la memoria está muy ajustada, se reciclará y no se reciclará en otras ocasiones, por lo que antes de usarla, debe determinar si está nulo para determinar si se ha reciclado.
3) referencia débil: implementada a través de la clase de referencia débil, por ejemplo, didáctica <oman> p = nueva referencia de débil <oman> (nueva persona ("lluvia")); Independientemente de si la memoria es suficiente, el sistema definitivamente se reciclará durante la recolección de basura.
4) Cita virtual: no se puede usar solo, se usa principalmente para rastrear el estado del objeto que se recoge la basura. Implementado a través de la clase Phantomreference y la clase de referencia de referencia de referencia, por ejemplo:
prueba de paquete; import java.lang.ref.phantomreference; import java.lang.ref.referenceue; prueba de clase pública {public static void main (string [] args) {// crea una persona de objeto persona = nueva persona ("Sunny"); // crear una cola de referencia referenceQueue <Oll> rq = new RefectionQueue <PERO> (); // Crear una referencia virtual, deje que esta referencia virtual de referencia al objeto de persona Phantomreference <PERO> PR = new Phantomreference <OPERA> (persona, RQ); // Acomoda las variables de referencia y objetos de la persona Referencias Persona = NULL; // Intenta obtener el objeto referenciado por la referencia virtual // Descubrí que el programa no puede acceder al objeto referenciado a través de la referencia virtual, por lo que la salida aquí es null system.out.println (pr.get ()); // sistema de recolección de basura forzada.gc (); System.runFinalization (); // porque una vez que se recicla el objeto en la referencia virtual, la referencia virtual ingresará la cola de referencia //, por lo que use la referencia ingresó primero la cola en la cola para comparar con PR, y salida verdadera system.out.println (rq.poll () == PR); }}Resultados de ejecución:
3. Mecanismo de recolección de basura de Java
De hecho, la recolección de basura de Java hace dos cosas: 1) Reciclaje de memoria 2) Desfragmentación
3.1 Algoritmo de recolección de basura
1) El reciclaje en serie (solo una CPU) y el reciclaje paralelo (múltiples CPU son útiles): el reciclaje en serie significa que no importa cuántas CPU tenga el sistema, siempre es solo una CPU realizar operaciones de recolección de basura. El reciclaje paralelo significa dividir todo el trabajo de reciclaje en múltiples partes, cada parte es responsable por una CPU, de modo que múltiples CPU se pueden reciclar en paralelo. El reciclaje paralelo es muy eficiente en la ejecución, pero aumenta la complejidad, y también hay algunos efectos secundarios, como el aumento aleatorio de la memoria.
2) Ejecución concurrente y parada de aplicación: como su nombre indica, su método de recolección de basura causará la suspensión de la aplicación mientras realiza la recolección de basura. Aunque la recolección de basura de la ejecución concurrente no hará que la aplicación se detenga, porque la ejecución de la basura de la ejecución concurrente necesita resolver conflictos con la aplicación (la aplicación puede modificar los objetos durante el proceso de recolección de basura), la sobrecarga del sistema de ejecución concurrente de recolección de basura es más alta que la de la parada del mundo, y requiere más memoria de montón cuando se ejecuta.
3) Complete y no compresión y copia:
① El recolector de basura que admite la compresión (compresión Mark = Mark-Clar + Compression) reubicará todos los objetos accesibles y luego reciclará toda la memoria ocupada anteriormente, reduciendo la fragmentación de la memoria.
② El recolector de basura sin comprimir (Mark-Clear) debe atravesarse dos veces. La primera vez que primero accede a todos los objetos accesibles y los marque como estados accesibles. La segunda vez que facilita toda el área de memoria y recicla objetos que no son marcados estados accesibles. Este método de reciclaje no está comprimido y no requiere memoria adicional, pero producirá fragmentación si se requiere dos recorridos.
③ Copie el recolector de basura: divida la memoria del montón en dos espacios idénticos, acceda a cada objeto accesible asociado desde la raíz (similar al vértice inicial del gráfico dirigido anterior), copie todos los objetos accesibles en el espacio A al espacio B y luego recicle el espacio A a la vez. Para este algoritmo, debido a que solo necesita acceder a todos los objetos accesibles, copiar todos los objetos accesibles y reciclar directamente todo el espacio, ignorar los objetos inalcanzables en absoluto, el costo de atravesar el espacio es pequeño, pero requiere grandes costos de copia y más memoria.
3.2 Reciclaje generacional de la memoria del montón
1) La base para el reciclaje generacional:
① La duración del tiempo de supervivencia del objeto: la mayoría de los objetos se reciclan durante el período joven ② Diferentes generaciones adoptan diferentes estrategias de reciclaje de basura: nuevos (tiempo de supervivencia corto) antiguo (tiempo de supervivencia largo) rara vez tienen referencias entre objetos
2) Generación de la memoria del montón:
① Generación joven:
Ⅰ Mecanismo de reciclaje: Debido a que el número de objetos es pequeño, se usa la replicación y el reciclaje.
Ⅱ Área de consolidación: consta de 1 área de Eden y 2 áreas de sobrevivientes. Dos áreas de sobrevivientes al mismo tiempo, una se usa para salvar el objeto y la otra está vacía; Cada vez que se lleva a cabo la recolección de basura de la generación joven, los objetos accesibles en el Edén y desde se copian en el área, y algunos de los de larga duración se copian a la vejez, luego el Edén y desde el espacio se limpia, y finalmente el original al espacio se convierte en el espacio, y el original desde el espacio se convierte en espacio.
Ⅲ Fuente del objeto: la mayoría de los objetos se asignan primero al área del Edén, y algunos objetos grandes se asignarán directamente a la generación anterior.
Ⅳ frecuencia de reciclaje: debido a que la mayoría de los objetos de generación jóvenes ingresan rápidamente a un estado inalcanzable, la frecuencia de reciclaje es alta y la velocidad de reciclaje es rápida.
② Vold Generation:
Ⅰ Mecanismo de reciclaje: use el algoritmo de compresión de marca para recuperarse.
Ⅱ Fuente de objetos: 1. El objeto grande entra directamente en la vejez.
2. Frecuencia de reciclaje de objetos accesibles con un largo tiempo de supervivencia en la generación joven: debido a que pocos objetos mueren, la frecuencia de ejecución no es alta y lleva mucho tiempo completarse.
③ Generación Permanente:
ⅠPurpose: Se utiliza para cargar clase, método y otra información. El valor predeterminado es de 64 m y no se reciclará. ⅡEngente Fuente: Ej.: Para marcos como Hibernate y Spring que, como las clases de generación dinámica de AOP, a menudo generan una gran cantidad de clases de proxy dinámicas, por lo que se necesita memoria de generación más permanente. Por lo tanto, a menudo nos encontramos con java.lang.OUTOFMemoryError: Error de espacio de Permgen al depurar Hibernate. Este es el error causado por el agotamiento de la memoria de generación permanente.
Ⅲ frecuencia de reciclaje: no se reciclará
3.3 recolectores de basura comunes
1) Reciclador en serie (solo se usa una CPU): Young Generation usa algoritmo de copia en serie; Old Generation utiliza algoritmo de compresión de marca en serie (tres etapas: marca de marca - barrido transparente - compresión compacta), el programa se detendrá durante el período de reciclaje.
2) Reciclador paralelo: el algoritmo utilizado para la generación joven es el mismo que el reciclador en serie, pero solo agrega procesamiento paralelo de CPU múltiples; El procesamiento de la antigua generación es exactamente el mismo que el del reciclador en serie, y sigue siendo un solo hilo.
3) Colector de compresión paralelo: el procesamiento de la generación joven es exactamente el mismo algoritmo que el del colector paralelo; Pero se utilizan diferentes algoritmos para la generación antigua, que en realidad se divide en diferentes regiones y luego algoritmo de etiquetado y compresión:
① Divida la vieja en varias áreas fijas;
② Etapa de marca (paralelo de múltiples subprocesos), marcando objetos accesibles;
③ Etapa resumida (ejecución en serie). Cuando encuentra un área que alcanza el valor numérico (baja densidad de objetos) desde la izquierda, esta área y su área derecha se comprimen y recuperan. El extremo izquierdo es el área densa ④ Etapa compacta (paralelo múltiple), identifique las áreas que deben cargarse y copiar los datos en estas áreas en paralelo. Después de este proceso, hay una gran cantidad de objetos activos en un extremo de la antigua generación y una gran pieza de espacio en el otro extremo.
4) Identificación concurrente: limpieza y reciclaje (CMS): el procesamiento de la generación joven es exactamente el mismo algoritmo que el de los recicladores paralelos; Pero se utilizan diferentes algoritmos para la generación antigua, pero el algoritmo de limpieza de marca todavía se usa:
① Identificación inicial (pausa del programa): marca el objeto directamente referenciado (objeto de primer nivel);
② Identificación concurrente (ejecución del programa): encuentre otros objetos accesibles a través de objetos de primer nivel;
③ Re-mark (pausa del programa): objetos de re-marcaje paralelo de múltiples subprocesos que pueden haberse perdido debido a la concurrencia (simplemente hablando, es anti-la falla)
④ Limpieza concurrente (ejecución del programa)
4. Consejos de gestión de memoria
1) Intente usar la cantidad directa, por ejemplo: String javastr = "El proceso de crecimiento del aprendizaje de la escuela primaria";
2) use StringBuilder y StringBuffer para realizar la concatenación de cadenas y otras operaciones;
3) Libere objetos inútiles lo antes posible;
4) Intente usar variables estáticas lo menos posible;
5) Caché de objetos comúnmente utilizados: se pueden implementar utilizando la caché de código abierto de código abierto, por ejemplo: Oscache, ehcache;
6) Intente no usar el método Finalize ();
7) Puede considerar usar Softreference de referencia suave cuando sea necesario.
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.