JVM y gestión de memoria

Una breve comprensión de JVM y la gestión de memoria.

1.1 JVM

ClassLoader incluye el cargador de clases de arranque (inicia el cargador de clases y carga la API principal), ExtClassLoader (carga la API de extensión) y AppClassLoader (carga clases personalizadas, es decir, Clase en el directorio de configuración CLASSPATH).

Proceso de carga de ClassLoader

Al ejecutar un programa, la JVM se inicia, ejecuta el cargador de clases de arranque, luego llama a ExtClassLoader y finalmente carga AppClassLoader.

métodos importantes

  • ClassLoader.loadClass() es la función de entrada de ClassLoader.
    definición:
	Class loadClass(String name, boolean resolve);

El nombre es la clase cargada por la JVM, como Foo o java.lang.Object. El parámetro de resolución le dice al método si necesita resolver la clase.

  • forName
    es similar al método loadClass, utilizado para cargar clases. El parámetro de resolución loadClass tiene por defecto false, lo que significa que la clase no se analiza ni se inicializa. ForName es lo contrario.

1.2i++

i++, ++i, i–, --i, son las diferencias en el orden de incremento y decremento de i.
Unos pocos ejemplos pueden ilustrar esto claramente.

int i,j,k,m,n=0;
i = i++ + ++i + ++i;
j = ++j + j++ + j++;
k = k++ + k++ + ++k;
n=m++;
m=++n;

'i++' y otros incrementos se consideran una declaración de ejecución, y el siguiente '+' es un operador.
Tome la segunda línea de código para resolver i como ejemplo.
Proceso de cálculo:
i=0+2+3=5
primero ejecute i ++, i es 0 en este momento, cuando la ejecución alcanza el signo '+', i ++ se incrementa, i es 1 en este momento, luego ejecute ++ i, i es 2 en este momento, y luego Ejecute ++i, i es 3 en este momento.
De la misma forma, el proceso de cálculo para resolver j, k, n, m es el siguiente:
j=1+1+2=4
k=0+1+3=4
n=0
m=1

1.3 Operadores y excepciones

operador

Operación ternaria: s=a?b:c;equivalente a if a : s=b; else s=c;
convertir automáticamente el tipo de datos a la derecha de ':' al tipo de datos de la izquierda. Cuando el tipo de datos de la izquierda es una constante, se puede mantener el tipo de datos de la derecha.

Operadores de bits: & && | ||
las operaciones de bits & y | se tratan como AND o (binario).
En operaciones lógicas booleanas, & y && son equivalentes y | es lo mismo. La diferencia es && ||que es una operación de cortocircuito y & |una operación sin cortocircuito.

anormal

La diferencia entre final, finalmente y finalizar

  • final
    Las clases finales no se pueden heredar y no se pueden derivar nuevas subclases;
    se garantiza que los métodos o variables finales no se cambiarán durante el proceso de llamada, es decir, no se pueden modificar ni reescribir.
  • Finalmente
    proporciona un bloque finalmente para realizar operaciones de limpieza durante el manejo de excepciones. intentar → capturar → finalmente
  • finalizar
    libera recursos compartidos y otros trabajos de limpieza. antes de que el recolector de basura lo borre de la memoria.

reflexión

La reflexión se refiere principalmente a un tipo de aplicación en la que un programa puede acceder, detectar y modificar su propio estado o comportamiento.

1.4 Pasaje y Referencia

Pasar por valor y pasar por referencia.

Para variables de tipo básico, JAVA es una copia por valor;
para variables de tipo objeto, JAVA es una copia por referencia.
(La cadena es una variable de tipo de objeto)
(En C++, cuando el parámetro es un tipo de referencia, se pasa una referencia real en lugar de una copia).

flujo de entrada/salida

Hay dos métodos en las operaciones IO de JAVA: orientado a bytes (Byte) y orientado a caracteres (Character).
La orientación a bytes
opera con datos binarios en unidades de 8 bits. Ambas son subclases de InputStream y OutputStream.
Los sufijos InputStream y OutputStream son flujos de bytes.
Operación orientada a caracteres
en unidades de caracteres. La lectura de archivos convierte datos binarios en caracteres y la escritura de archivos convierte caracteres en datos binarios. Ambas son subclases de Reader y Writer.
Lector y Escritor son flujos de caracteres.

Publicación por entregas

La implementación de la serialización puede convertir un objeto que implementa la interfaz serializable en un conjunto de bytes. El objeto se puede reconstruir restaurando los datos del byte más adelante.
Puede lograr una persistencia ligera (persistencia ligera). El objeto sigue vivo entre llamadas al programa. Leyendo y escribiendo en el disco.
Características importantes :

  • Implemente la invocación de método remoto (RMI) de JAVA: llame a objetos en otras máquinas como si llamara a objetos en su propia máquina.
  • JavaBean: Guardado de información de estado.

2. Gestión de memoria JAVA

2.1 Recolección de basura

Java asigna memoria automáticamente cuando se crea un objeto y libera esta memoria cuando ya no existe una referencia al objeto.
El hilo de recolección de basura tiene baja prioridad y no se ejecutará en circunstancias normales.
La ejecución solo se activará cuando la máquina virtual esté inactiva o la memoria del montón actual sea insuficiente.
Mecanismo de recolección de basura: el método estático gc() en la clase System puede ejecutar el recolector de basura y se ejecuta en la JVM. Llamar a este método es iniciar una aplicación y se desconoce el estado de ejecución, es decir, es posible que no se recicle de inmediato.
Es mejor utilizar protected void finalize() throws Throwablela terminación forzada manual del objeto o personalizar el método de finalización.

El mecanismo de implementación específico de la entrevista de la máquina virtual JVM

2.2 Gestión de la memoria

La JVM se divide en área de montón , área de pila y área de método . Las instancias de objetos inicializados se colocan en el montón, las referencias se colocan en la pila y los grupos constantes de información de clase (constantes estáticas y variables estáticas) se colocan en el área del método.
El montón se divide en la nueva generación y la antigua generación (java8 canceló la generación permanente y adoptó Metaspace), la nueva generación contiene el área Eden + Survivor , y el área Survivor se divide en áreas desde y hacia .
Durante el reciclaje de memoria, si se utiliza un algoritmo de copia, copiando de a a, después de uno o más GC, los objetos supervivientes se moverán.
Cuando la memoria JVM no es suficiente, se activará FGC (GC completo) para limpiar el área antigua de JVM. Cuando la nueva área esté llena, se activará MGC (GC menor). Los objetos supervivientes primero se colocarán en una de las áreas de servicio y luego se limpiará la basura. Porque si solo limpia los objetos que deben eliminarse, esto provocará la fragmentación de la memoria, por lo que Eden generalmente se limpia por completo y luego se organiza la memoria. Luego, la próxima vez que se realice GC, se usará el siguiente Survive y se usará en un bucle.
Herramientas de depuración de memoria de uso común : jmap, jstack, jhat
jmap verifica la información de la memoria, jstack verifica la situación actual de la pila y jhat verifica la información del montón de volcado.

pérdida de memoria

Pueden producirse pérdidas de memoria si no se libera la memoria asignada no utilizada.

Cómo comprobar si hay pérdidas de memoria:

  1. Utilice las propias fugas de Xcode para comprobar dinámicamente las pérdidas de memoria:
    seleccione Xcode -> Abrir herramienta de desarrollo -> Instrumentos -> Herramienta de fugas
  2. Usando código (reescribiendo el método dealloc)
    Aunque la herramienta Leaks es poderosa, no puede detectar pérdidas de memoria causadas por referencias circulares de bloques. En este caso, generalmente necesita solucionar el problema usted mismo. El método infalible es reescribir el método dealloc del objeto. Método para monitorear si el objeto es normal. Suelte para confirmar que no se forma ninguna referencia circular.

La base teórica es: al acceder a la memoria, verificar la validez del acceso a la memoria comparando la memoria accedida con la memoria realmente asignada por el programa.

Supongo que te gusta

Origin blog.csdn.net/qq_32301683/article/details/104380855
Recomendado
Clasificación