Preguntas frecuentes de la entrevista JVM

Tabla de contenido

1. Proceso e hilo

 Dos, proceso JVM

3. JVM

División del área de memoria JVM

Carga de clases JVM

Proceso de carga de clases

 Recolección de basura (GC) de JVM

 1. En la recolección de basura, ¿qué se recicla?

 2. ¿Cómo determinar si el objeto necesita ser reciclado?

3. Luego de determinar los objetos a reciclar, ¿cómo realizar la recolección de basura?


1. Proceso e hilo

Antes de hablar sobre estos temas de la JVM, revisemos la relación entre subprocesos y procesos.

  • Un proceso puede verse como el proceso de ejecución de un programa. La ejecución de un programa requiere recursos como tiempo de CPU, espacio de memoria, archivos y E/S. El sistema operativo asigna estos recursos en unidades de procesos, por lo que un proceso es la unidad básica de asignación de recursos.
  • Los subprocesos pertenecen al proceso y solo pueden estar activos dentro del proceso. Varios subprocesos comparten los recursos que posee el proceso. Si el proceso se considera como una colección de tareas que completan muchas funciones, entonces un hilo es un elemento de tarea en la colección, responsable de funciones específicas . Aunque recursos como CPU, memoria y E/S se asignan a los procesos, son los subprocesos los que realmente utilizan estos recursos y los ejecutan en la CPU, es decir, los subprocesos que realmente completan las funciones del programa.

Debido a que el proceso es el propietario de estos recursos, su carga es muy pesada y los gastos generales de tiempo y espacio en el proceso de creación, cambio y eliminación de procesos son muy grandes. Por lo tanto, los principales sistemas operativos actuales solo consideran el proceso como el propietario del recurso y asignan los atributos de programación y operación de la CPU al subproceso.

Por ejemplo, abrir un programa de navegador generará un proceso correspondiente. El proceso del navegador contiene muchos subprocesos, como subprocesos de solicitud HTTP, subprocesos de E / S, subprocesos de representación y subprocesos de respuesta a eventos. El proceso del navegador tiene memoria y recursos de E/S, etc., pero cuando ingresamos texto en el navegador, es la E/S en el proceso del navegador la que realmente usa los recursos de E/S para recibir el texto que ingresamos y procesar el texto en la CPU. /O hilo. Es decir, es el hilo el que realmente completa la función de entrada de texto del navegador.

 Muchos sistemas operativos modernos permiten que un proceso contenga múltiples subprocesos, mejorando así el paralelismo del programa y la utilización de los recursos.

 Dos, proceso JVM

Sabemos que el lenguaje Java debe ejecutarse en la JVM. De hecho, JVM también es un programa de software, lo que significa que cuando se ejecuta, también creará un proceso en el sistema operativo, es decir, un proceso JVM, generalmente llamado instancia JVM . Y el método principal que escribimos es en realidad dónde se encuentra el hilo principal del proceso JVM.

Desde la perspectiva del sistema operativo, el programa Java que solemos decir debe incluir la JVM y el código Java que escribimos.

Cuando terminemos de escribir el código Java y compilarlo en un archivo de clase, use el comando Java para ejecutar el método principal o inicie directamente el método principal en el IDE, el programa JVM se ejecutará y el sistema operativo lo cargará . la memoria del disco y crea un proceso JVM, luego inicia el hilo principal, y el hilo principal llamará al método principal de una determinada clase, por lo que este hilo principal es donde se encuentra el método principal que escribimos.

De hecho, la JVM en sí es una aplicación de subprocesos múltiples. Incluso si no creamos subprocesos manualmente en el código, el proceso de JVM no solo tiene un subproceso principal, sino que también tiene otros subprocesos. Estos subprocesos completan las funciones de la JVM, por ejemplo, el subproceso GC es responsable de reciclar objetos basura durante el uso de la JVM. Una vez iniciado el proceso JVM, debe haber subprocesos de la siguiente manera:

hilo efecto
principal El hilo principal ejecuta el método principal de la clase de inicio que especificamos
Controlador de referencia hilo que maneja referencias
Finalizador El hilo que llamó al método de finalización del objeto.
Despachador de señales Envía subprocesos que manejan señales enviadas a la JVM.
Adjuntar oyente El hilo responsable de recibir comandos externos.

Hasta ahora, sabemos que iniciar un programa Java es esencialmente iniciar un programa JVM y crear un proceso JVM en el sistema operativo. El sistema operativo asignará muchos recursos a este proceso JVM, como memoria, E/S, etc. El proceso JVM contiene muchos subprocesos, y estos subprocesos comparten los recursos asignados por el proceso JVM. Al mismo tiempo, estos subprocesos también son entidades ejecutadas en el núcleo de la CPU y completan las funciones de la JVM.

Al mismo tiempo, también podemos descubrir a través de experimentos cuántos programas Java se inician y cuántos procesos JVM (instancias JVM) se crearán. Cada instancia es independiente y no se afecta entre sí, es decir, un programa (un programa de software JVM) puede ser compartido por múltiples procesos (creando múltiples procesos JVM o instancias JVM)

3. JVM

División del área de memoria JVM

En general, la JVM se puede dividir aproximadamente en cuatro partes:

  • la pila
  • montón
  • área del método
  • contador de programa

¡Todos deberían estar familiarizados con las variables en Java! Las variables se dividen en variables globales, variables locales y variables estáticas.

Consejo: Aquí todo el mundo debería hablar principalmente sobre la pila y el montón en la JVM, que es diferente de la pila y el montón en el sistema operativo y de la pila y el montón en la estructura de datos. Cuando le pregunten sobre pilas y montones en el futuro, debe averiguar dónde están las pilas y los montones.

Por ejemplo

public class test {
    public int a; // 全局变量(也可叫做test这个类的成员变量)
    public static int b; // 静态变量
    public void method() {
        int c = 0; // 局部变量
        System.out.println("这是test这个类的一个普通成员方法");
    }
    public static void run() {
        System.out.println("这是一个静态方法!"); // 静态方法不需要借助实例化对象
    }
    public static void main(String[] args) {
        test test1 = new test(); // test1 是test类的一个实例化对象
        test test2 = new test(); // test2 是另一个实例化对象
    }
}
  1.  Nuestras variables locales se almacenan en la pila. Las variables globales son parte de nuestros nuevos objetos instanciados y se almacenan en el montón. Las variables estáticas son especiales porque se almacenan en el área de métodos.
  2. Entonces, ¿qué más hay en nuestra pila? También existe la relación de llamada entre los distintos métodos de nuestra clase.

De vuelta en el montón, nos damos cuenta de que nuestros nuevos objetos instanciados se almacenan en el montón, y cada uno de nuestros objetos instanciados tiene sus variables y métodos correspondientes (es decir, nuestros métodos miembro y variables miembro). con los objetos.

¿Qué pasa con las variables estáticas y los métodos estáticos?

No pertenecen a los objetos que creamos instancias, existen cuando se crea nuestra clase y no dependen de objetos instanciados. Pertenecen a objetos de clase y los colocamos en el área de métodos como objetos de clase.

Entonces, ¿qué hay en el objeto de clase?

¿Cómo se llama la clase de inclusión?

¿Quién hereda e implementa esas interfaces?

¿Cuáles son los atributos, cuál es el nombre del atributo, cuál es el tipo, cuál es el permiso de acceso?

¿Hay algún método, nombre del método?, ¿Parámetros? valor de retorno? ¿permiso de acceso? ¿Cuál es la instrucción dentro del método? ¿Qué se hace en el método?

En resumen, el objeto de clase describe nuestra clase como un todo. Una clase puede tener múltiples objetos instanciados, pero solo hay un objeto de clase (es decir, cada variable estática y método estático tiene solo uno en diferentes objetos instanciados).

resumámoslo

  • Pila (relación de llamada entre métodos, variables locales)
  • Montón (objetos instanciados: variables globales (también llamadas variables miembro), métodos miembro)
  • Área de métodos (objetos de clase: variables estáticas, métodos estáticos....)

Ah, por cierto, aún nos queda el contador de programas.

 Como dijimos anteriormente, cuando iniciamos Java e iniciamos el método principal, nuestro programa JVM se ejecutará, se creará un proceso JVM y habrá varios subprocesos responsables de completar el trabajo de la JVM. Entonces me gustaría preguntar: ¿cada hilo tiene las cuatro áreas anteriores?

No, nuestra área de método y nuestro montón tienen solo una copia en todo el proceso JAVA (varios subprocesos en el proceso comparten este recurso), pero cada subproceso tiene una copia del contador y la pila del programa.

por qué:

Los recursos relacionados, como la CPU del sistema operativo, se asignan a un proceso, y todos los subprocesos del proceso comparten todos los recursos del proceso, y el subproceso es la unidad básica de ejecución.

Cada hilo ejecuta su propio código y cada uno es un flujo de ejecución, por lo que cada hilo necesita saber qué instrucción ejecutar a continuación (la función del contador del programa). Cada hilo también necesita registrar la pila de llamadas actual (hay un área de método)

Carga de clases JVM

Cuando se inicia el programa Java, es necesario dejar que la JVM lea el archivo de clase en la memoria y realice una serie de trabajos de seguimiento.

Proceso de carga de clases

1. Cargar Busque el archivo de clase, abra el archivo, lea el archivo y cree un objeto de clase vacío

2. Enlace

  • Validación: comprueba que el formato del archivo .class se ajuste a los requisitos de la especificación (descritos explícitamente en la especificación JVM).
  • Preparación: asigne espacio de memoria para variables estáticas y llene el espacio con valores 0.
  • Análisis: inicializa la constante de cadena y reemplaza "referencias conformes con referencias directas"

3. Inicialización

Inicialice los miembros estáticos de la clase y ejecute el bloque de código estático. Si la clase principal de esta clase aún no se ha cargado, la clase principal también debe cargarse

En la entrevista, lo que más le gusta probar al entrevistador es: "modelo de delegación de padres" (describe la fase de carga en la carga de clases, vaya a esos directorios para buscar archivos .class

Para comprender el llamado modelo de delegación parental, necesitamos saber : cargador de clases: un módulo especial en la JVM, que es responsable de cargar clases y completar el trabajo de carga de clases.

 


 Recolección de basura (GC) de JVM

¿Aún recuerdas? En lenguaje C, solicitamos memoria dinámicamente a través de malloc (la memoria aplicada está en el montón) y necesitamos liberar la memoria manualmente (libre) después de cada aplicación. Si no se publica, provocará graves problemas, como pérdidas de memoria.

Pero si solo esperamos que nuestros programadores liberen memoria manualmente, obviamente no es confiable.

Porque en Java, la máquina es responsable de recuperar el espacio de memoria que ya no se utiliza; este mecanismo se denomina mecanismo de recuperación de memoria (recolección de basura denominada GC)

 1. En la recolección de basura, ¿qué se recicla?


 2. ¿Cómo determinar si el objeto necesita ser reciclado?

 Entonces sabemos que la unidad de reciclaje es un objeto, entonces, ¿cómo determinamos específicamente que un objeto es basura (ya no se usa)?

Hay muchas formas de determinar si se trata de basura. Entre ellos, el método de "análisis accesible" se utiliza principalmente en Java y el método de "recuento de referencias" se utiliza en otros lenguajes de programación (como Python).

En el libro "Comprensión profunda de la máquina virtual Java", se mencionan ambos métodos.

  • Entonces, si nos preguntan en la entrevista: En el mecanismo de recolección de basura, ¿cómo juzgar si el objeto es basura? Puedes decir ambas cosas.
  • ​​​Si pregunta: Cómo juzgar si un objeto es basura en la JVM, solo necesita responder "análisis de accesibilidad".

 conteo de referencia

Utilice contadores adicionales para registrar cuántas referencias a un objeto apuntan a él.

Si desea utilizar un objeto, debe tener una referencia que apunte a él. Si la referencia es inútil (el recuento de referencias es 0), significa que el objeto no se puede utilizar, es decir, basura que debe reciclarse.

Análisis de accesibilidad (el enfoque que realmente adopta Java)

Accesibilidad, ¿a qué te refieres?

Es comenzar con algunas variables especiales en el código y luego activar desde el punto de partida para ver si se puede acceder a esos objetos. Siempre que se pueda acceder al objeto, se marca como "alcanzable", después de completar una ronda de marcado, el resto es "inalcanzable", es decir, ¡basura para reciclar! ! !

Expliquemos algunos de los sustantivos anteriores.

1. ¿Qué tipo de variable se puede llamar punto de partida (GCRoot)?

1. Referencias a objetos en la tabla de variables locales (variables locales en la pila, hay varias pilas, una para cada subproceso, y hay muchos marcos de pila en cada pila, y cada marco de pila tiene su propia superficie de variable local).

Significa: todas las variables en todas las tablas de variables locales de todas las pilas y todos los marcos de pila de todos los subprocesos pueden considerarse como GCRoot.

2. El objeto correspondiente en el grupo constante.

3. En el área de métodos, miembros de tipos de referencia estáticos.

2. ¿Qué es "accesible"?


3. Luego de determinar los objetos a reciclar, ¿cómo realizar la recolección de basura?

Hay varias notas sobre el algoritmo (estrategia) de recolección de basura clásico.

1. Marcar-Borrar

2. Copiar algoritmo (para resolver el problema de la fragmentación de la memoria)

3. Marcar y ordenar (similar a eliminar elementos en una tabla de secuencia)

 

 4. Reciclaje generacional

 

Resumir:

  1. En el área del Edén , si los objetos recién nacidos han sobrevivido a una ronda de GC ( una ronda de GC y la mayoría de los objetos han sido reciclados, un pequeño número de ellos han sobrevivido a una ronda de GC ), coloque estos objetos supervivientes en el área de supervivencia. área ( debido a que hay pocos objetos, el espacio en el área de supervivientes no es grande)
  2. Los objetos en el área de supervivientes utilizan el algoritmo de copia, debido a que el número es pequeño, no importa si se desperdicia la mitad de la memoria.
  3. Los objetos de la generación anterior utilizan el algoritmo de acabado de marcas, porque los objetos de la generación anterior no se reciclan con frecuencia, por lo que pueden recibir la sobrecarga causada por el acabado de marcas

Revisando el reciclaje generacional

 

 

4. Preguntas de elección comunes sobre JVM

Sentencia de GC Roots

Implementación de la JVM

 cargador de clases

 Diferencia entre recolector de basura y algoritmo de recolección de basura

partición de memoria JVM

Supongo que te gusta

Origin blog.csdn.net/weixin_61061381/article/details/127526356
Recomendado
Clasificación