La asignación y gestión de memoria de Java son una de las tecnologías centrales de Java. Anteriormente hemos introducido el conocimiento de la gestión de la memoria de Java, la fuga de memoria y la recolección de basura de Java. Hoy, una vez más profundizaremos en el núcleo de Java e introduciremos en detalle el conocimiento de Java en la asignación de memoria. En general, Java implicará las siguientes áreas al asignar memoria:
◆ Registrarse: no podemos controlarlo en el programa
◆ Pila: almacena tipos básicos de datos y referencias a objetos, pero el objeto en sí no se almacena en la pila, pero se almacena en el montón (el objeto que sale de nuevo)
◆ Monta: almacenar datos generados utilizando nuevos
◆ Dominio estático: miembros estáticos almacenados en un objeto definido con estática
◆ Piscina constante: las constantes de la tienda
◆ Almacenamiento no RAM: espacio de almacenamiento permanente como el disco duro
Pila en la asignación de memoria de Java
Algunos tipos básicos de datos variables definidos en la función y las variables de referencia del objeto se asignan en la memoria de la pila de la función.
Cuando una variable se define en un bloque de código, Java asigna el espacio de memoria para la variable en la pila. Cuando la variable sale del alcance, Java liberará automáticamente el espacio de memoria asignado para la variable, y el espacio de memoria se puede usar por separado de inmediato. El tamaño de los datos y el ciclo de vida en la pila son ciertos, y estos datos desaparecen cuando no apunta a los datos.
Montón en la asignación de memoria de Java
La memoria Heap se usa para almacenar objetos y matrices creados por New. La memoria asignada en el montón es administrada por el colector de basura automático de Java Virtual Machine.
Después de generar una matriz u objeto en el montón, se puede definir una variable especial en la pila, de modo que el valor de esta variable en la pila es igual a la primera dirección de la matriz u objeto en la memoria del montón, y la variable en la pila se convierte en una variable de referencia para la matriz u objeto. Una variable de referencia es equivalente a un nombre dado a una matriz u objeto. Puede usar las variables de referencia en la pila en el programa para acceder a la matriz u objeto en el montón. Una variable de referencia es equivalente a un nombre dado a una matriz u objeto.
Las variables de referencia son variables ordinarias, que se asignan en la pila cuando se definen. Las variables de referencia se lanzan después de que el programa se ejecuta fuera de su alcance. La matriz y el objeto en sí se asignan en el montón. Incluso si el programa se ejecuta fuera del bloque de código donde las declaraciones que usan nuevas para generar la matriz u objeto se encuentran, la memoria ocupada por la matriz y el objeto en sí no se lanzará. La matriz y el objeto solo se convierten en basura cuando no hay una variable de referencia que le apunte y no se pueda usar, pero aún así ocupan el espacio de memoria. Es recolectado (liberado) por el recolector de basura en un momento incierto. Esta es también la razón por la cual Java toma más memoria.
De hecho, las variables en la pila apuntan a variables en la memoria de montón, ¡que es el puntero en Java!
Montón
El montón de Java es un área de datos de tiempo de ejecución, desde el cual los objetos asignan el espacio. Estos objetos se establecen a través de instrucciones como New, NewArray, Anewarray y MultianewArray. No requieren que el código del programa se publique explícitamente. El montón es responsable de la recolección de basura. La ventaja del montón es que puede asignar dinámicamente el tamaño de la memoria, y la vida útil no tiene que ser contada al compilador de antemano, porque asigna dinámicamente la memoria en tiempo de ejecución. El recolector de basura de Java recopilará automáticamente los datos que ya no se usan. Pero la desventaja es que debido a que necesita asignar dinámicamente la memoria en tiempo de ejecución, la velocidad de acceso es más lenta.
La ventaja de la pila es que la velocidad de acceso es más rápida que el montón, solo solo de los registros, y los datos de la pila se pueden compartir. Pero la desventaja es que el tamaño de los datos y la vida útil en la pila deben ser deterministas y carecer de flexibilidad. La pila almacena principalmente algunos tipos básicos de datos variables (int, corto, largo, byte, flotante, doble, booleano, char) y manijas de objetos (referencias).
Una característica especial muy importante de la pila es que los datos existentes en la pila se pueden compartir. Supongamos que definimos al mismo tiempo:
Código Java
int a = 3;
int b = 3;
El compilador primero procesa int a = 3; Primero, creará una referencia en la pila con una variable A, y luego descubrirá si hay un valor de 3 en la pila. Si no se encuentra, almacenará 3 y luego apuntará a 3. Luego procese int b = 3; Después de crear la variable de referencia de B, porque ya hay un valor de 3 en la pila, B se apunta directamente a 3. De esta manera, A y B apuntan a 3 al mismo tiempo.
En este momento, si a = 4 se establece nuevamente; Luego, el compilador buscará nuevamente si hay un valor de 4 en la pila. Si no, almacene 4 y apunte a 4; Si ya existe, apunte directamente a esta dirección. Por lo tanto, el cambio en el valor A no afectará el valor b.
Cabe señalar que este intercambio de datos es diferente del intercambio de referencias de dos objetos que apuntan a un objeto al mismo tiempo, porque en este caso la modificación de A no afectará B, el compilador lo hace, que es propicio para guardar espacio. Una variable de referencia del objeto modifica el estado interno de este objeto y afectará otra variable de referencia del objeto.
Código Java
1.int i1 = 9;
2.int i2 = 9;
3.int i3 = 9;
4. Public Static final int int1 = 9;
5. Public static final int int2 = 9;
6. Public static final int int3 = 9;
Para variables de miembros y variables locales: las variables miembros son variables definidas dentro del método y la clase; Las variables locales son variables definidas dentro del método o bloque de declaración. Las variables locales deben ser inicializadas.
Los parámetros formales son variables locales, y los datos de las variables locales existe en la memoria de la pila. Las variables locales en la memoria de la pila desaparecen a medida que desaparece el método.
Las variables miembros se almacenan en objetos en el montón y son recolectadas por el recolector de basura.
Como en el siguiente código:
Código Java
Class Birth Date {Private int Day; Mes privado int; Private Int Year; Public Birth Date (int d, int m, int y) {day = d; mes = m; año = y; } omit Get, establecer método ……} Test de clase pública {public static void main (string args []) {int date = 9; Prueba test = new test (); test.change (fecha); Fecha de nacimiento D1 = nueva fecha de nacimiento (7,7,1970); } public void Change1 (int i) {i = 1234; }Para el código anterior, la fecha es una variable local, I, D, M, Y son todos los parámetros formales como variables locales, y el día, el mes y el año son variables miembros. Analicemos los cambios durante la ejecución del código:
1. El método principal comienza a ejecutar: int date = 9;
Las variables locales de fecha, los tipos básicos, las referencias y los valores están presentes en la pila.
2. Test Test = New Test ();
La prueba es una referencia de objeto, existe en la pila y el objeto (nuevo test ()) existe en el montón.
3. Test.change (fecha);
I es una variable local, y la referencia y el valor están presentes en la pila. Cuando se ejecute el cambio de método, desapareceré de la pila.
4. Fecha de nacimiento D1 = nueva cita de nacimiento (7,7,1970);
D1 es una referencia de objeto y existe en la pila. Los objetos (New Birth Date ()) existen en el montón, donde D, M, Y son variables locales almacenadas en la pila, y sus tipos son los tipos de base, por lo que sus datos también se almacenan en la pila. Día, mes, año son variables miembros, y se almacenan en el montón (nueva fecha de nacimiento ()). Cuando se ejecute el constructor de la fecha de nacimiento, D, M, Y desaparecerán de la pila.
5. Después de ejecutar el método principal, la variable de fecha, la prueba y la referencia D1 desaparecerán de la pila, y la nueva prueba (), la nueva fecha de nacimiento () esperará la recolección de basura.
Piscina constante
Los grupos constantes se refieren a algunos datos que se determinan durante el período de compilación y se guarda en el archivo .class compilado.
Además de contener los valores constantes (finales) de varios tipos básicos (como int, long, etc.) y tipos de objetos (como cadenas y matrices) definidos en el código, también contiene algunas referencias simbólicas en forma de texto, como:
◆ Los nombres totalmente calificados de clases e interfaces;
◆ El nombre y el descriptor del campo;
◆ Métodos y nombres y descriptores.
Si el período de compilación se ha creado (definido directamente en cotizaciones dobles), se almacenará en el grupo constante, y si puede ser determinado por el período de ejecución (de nuevo), se almacenará en el montón. Para las cuerdas con iguales, siempre hay solo una copia en el grupo constante y una copia múltiple en el montón.
La cadena es un datos de embalaje especiales. Se puede usar:
Código Java
String str = new String ("ABC"); String Str = "ABC";Hay dos formularios para crear. El primero es usar nuevo () para crear un nuevo objeto, que se almacenará en el montón. Se crea un nuevo objeto cada vez que se llama. El segundo tipo es crear primero una variable STR al objeto de la clase de cadena en la pila, y luego usar una referencia simbólica para averiguar si hay "ABC" en el grupo constante de cadena. Si no, almacene "ABC" en la piscina constante de cadena y deje que STR apunte a "ABC". Si ya hay "ABC", entonces STR apunte directamente a "ABC".
Al comparar si los valores en la clase son iguales, use el método igual (); Al probar si las referencias de las dos clases de envoltorio apuntan al mismo objeto, use == y use el siguiente ejemplo para ilustrar la teoría anterior.
Código Java
String str1 = "ABC"; String str2 = "ABC"; System.out.println (str1 == str2); //verdadero
Se puede ver que Str1 y Str2 apuntan al mismo objeto.
Código Java
String str1 = new String ("ABC"); String str2 = new String ("ABC"); System.out.println (str1 == Str2); // FALSOEl nuevo método es generar diferentes objetos. Generar uno a la vez.
Por lo tanto, de la segunda manera, se crean múltiples cadenas "ABC", y solo hay un objeto en la memoria. Este método de escritura es beneficioso y ahorra espacio de memoria. Al mismo tiempo, puede mejorar la velocidad de ejecución del programa hasta cierto punto, porque el JVM decidirá automáticamente si es necesario crear un nuevo objeto basado en la situación real de los datos en la pila. Para el código de cadena str = new String ("ABC");, se crean nuevos objetos en el montón independientemente de si sus valores de cadena son iguales o no, si es necesario crear nuevos objetos, aumentando así la carga en el programa.
Por otro lado, tenga en cuenta: cuando definimos una clase usando un formato como String Str = "ABC";, siempre damos por sentado que creamos un objeto STR de la clase de cadena. ¡Preocuparse por la trampa! ¡El objeto puede no haber sido creado! Y tal vez solo apunte a un objeto que se ha creado anteriormente. Solo a través del método nuevo () podemos asegurarnos de que se cree un nuevo objeto cada vez.
Varios ejemplos de problemas de agrupación constante de cadenas
Ejemplo 1:
Código Java
String S0 = "Kvill"; String S1 = "Kvill"; String S2 = "KV" + "Ill"; System.out.println (S0 == S1); System.out.println (S0 == S2); El resultado es: Truetrue
Análisis: En primer lugar, necesitamos saber que el resultado es que Java asegurará que una constante de cadena tenga solo una copia.
Debido a que S0 y S1 en el ejemplo son constantes de cadena, se determinan durante el período de compilación, por lo que S0 == S1 es verdadero; y "KV" y "Ill" también son constantes de cadena. Cuando una cadena está conectada por múltiples constantes de cadena, definitivamente también es una constante de cadena, por lo que S2 también se analiza en una constante de cadena durante el período de compilación, por lo que S2 también es una referencia a "Kvill" en el grupo constante. Entonces obtenemos S0 == S1 == S2;
Ejemplo 2:
Ejemplo:
Código Java
Análisis: Las cadenas creadas con nueva cadena () no son constantes y no se pueden determinar durante el período de compilación, por lo que las cadenas creadas por New String () no se colocan en el grupo constante, tienen su propio espacio de direcciones.
S0 también es una aplicación de "Kvill" en el grupo constante. S1 no se puede determinar durante el período de compilación, por lo que es una referencia al nuevo objeto "Kvill" creado en tiempo de ejecución. S2 no se puede determinar durante el período de compilación porque tiene la segunda mitad de la nueva cadena ("enfermo"), por lo que también es una aplicación del objeto recién creado "Kvill"; Si comprende esto, sabrá por qué se obtiene este resultado.
Ejemplo 3:
Código Java
Cadena a = "a1"; cadena b = "a" + 1; system.out.println ((a == b)); // resultado = true String a = "true"; String b = "A" + "True"; System.out.println ((a == b)); // resultado = true String a = "A3.4"; String B = "A" + 3.4; System.out.println ((a == b)); // resultado = verdadero
Análisis: para la conexión JVM de las constantes de cadena, el JVM optimiza la conexión "+" de la cadena constante al valor conectado después del período de compilación del programa. Tome "A" + 1 como ejemplo. Después de la optimización del compilador, ya es A1 en la clase. Durante el período de compilación, se determina el valor de la constante de cadena, por lo que el resultado final del programa anterior es verdadero.
Ejemplo 4:
Código Java
Cadena a = "ab"; string bb = "b"; string b = "a" + bb; system.out.println ((a == b)); // resultado = falso
Análisis: Para las referencias de cadena en JVM, ya que hay referencias de cadena en la conexión " +" de las cadenas, el valor referenciado no se puede determinar durante el período de compilación del programa, es decir, "A" + BB no puede optimizar por el compilador, y solo asigna dinámicamente y asigna la nueva dirección conectada a B durante el período de ejecución del programa. Por lo tanto, el resultado del programa anterior es falso.
Ejemplo 5:
Código Java
Cadena a = "AB"; String final bb = "b"; string b = "a" + bb; system.out.println ((a == b)); // resultado = verdadero
Análisis: La única diferencia entre [4] es que la cuerda BB está decorada con la modificación final. Para las variables modificadas finales, se analiza como una copia local del valor constante en el tiempo de compilación y se almacena en su propio grupo constante o se incrusta en su secuencia de código de byto. Entonces, en este momento, los efectos de "A" + BB y "A" + "B" son los mismos. Por lo tanto, el resultado del programa anterior es cierto.
Ejemplo 6:
Código Java
Cadena a = "ab"; cadena final bb = getBb (); cadena b = "a" + bb; system.out.println ((a == b)); // result = falsePrivate static string getBb () {return "b"; }Análisis: El JVM hace referencia a BB para cadenas, y su valor no se puede determinar durante el período de compilación. Solo después de llamar al método durante el tiempo de ejecución del programa, el valor de retorno del método y "a" están conectados dinámicamente y la dirección se asigna a b. Por lo tanto, el resultado del programa anterior es falso.
Acerca de la cadena es inmutable
Del ejemplo anterior, podemos averiguar:
Cadena S = "A" + "B" + "C";
Es equivalente a la cadena S = "ABC";
Cadena a = "a";
Cadena b = "b";
Cadena c = "c";
Cadena s = a + b + c;
Esto es diferente, el resultado final es igual a:
Código Java
StringBuffer temp = new StringBuffer (); temp.append (a) .append (b) .append (c); string s = temp.toString ();
De los resultados del análisis anteriores, no es difícil inferir que String use el operador de conexión (+) para analizar el motivo de la ineficiencia, como este código:
Código Java
prueba de clase pública {public static void main (string args []) {String s = null; para (int i = 0; i <100; i ++) {s+= "a"; }}}Cada vez que se realiza +, se genera un objeto StringBuilder, y luego lo agrega y lo tira. La próxima vez que llegue el bucle, se regenera un objeto StringBuilder y luego agregue la cadena, y el bucle se completa hasta que termine. Si usamos directamente el objeto StringBuilder para agregar, podemos guardar N - 1 tiempo para crear y destruir el objeto. Por lo tanto, para las aplicaciones que requieren concatenación de cadenas en un bucle, la operación de agregado generalmente se realiza utilizando los objetos StringBuffer o StringBulider.
Debido a la naturaleza inmutable de la clase de cadena, hay mucho que decir sobre esto. Siempre que sepa que la instancia de la cadena no cambiará una vez que se genere, por ejemplo: String Str = "KV"+"Ill"+""+"Ans"; Hay 4 constantes de cadena, primero "KV" y "Ill" generan "Kvill" en la memoria, y luego "Kvill" y "" "generan" Kvill "y" "y finalmente generan" KVILL ANS "; y asigne la dirección de esta cadena a STR, porque" Inmutable "de String genera muchas variables temporales, por lo que se recomienda usar StringBuffer, porque StringBuffer es cambiante.
Uso final y comprensión en la cadena
Código Java
Final StringBuffer a = new StringBuffer ("111"); final StringBuffer b = new StringBuffer ("222"); a = b; // Esta oración no se compila hasta que se termine. StringBuffer final a = new StringBuffer ("111"); A.Append ("222"); /// Compilar después de que esté terminadoSe puede ver que la final solo es válida para el "valor" referenciado (es decir, dirección de memoria). Fuerza a la referencia a solo apuntar al objeto al que inicialmente se señaló. Cambiar su señalización causará un error en el tiempo de compilación. En cuanto a los cambios en el objeto que señala, Final es irresponsable.
Resumir
La pila se utiliza para almacenar algunos datos variables locales del tipo de datos original y referencias a objetos (cadena, matriz, objeto, etc.) pero no almacena contenido de objetos
Los objetos creados usando la nueva palabra clave se almacenan en el montón.
Una cadena es una clase de envoltura especial, y sus referencias se almacenan en la pila, y el contenido del objeto debe determinarse de acuerdo con el método de creación (grupo constante y montón). Algunos se crean en el momento de la compilación y se almacenan en el grupo constante de cadena, mientras que otros se crean solo en tiempo de ejecución. Use la nueva palabra clave y almacenada en el montón.
El artículo anterior habla brevemente sobre la diferencia entre la asignación de memoria Java+ y la ubicación de almacenamiento de variables es todo el contenido que comparto con usted. Espero que pueda darle una referencia y espero que pueda apoyar más a Wulin.com.