Fuera de la memoria: en términos de laicos, significa que no hay suficiente memoria. Por ejemplo, crear constantemente un objeto grande en un bucle infinito pronto causará un desbordamiento de memoria.
Fugas de memoria: se refiere a la liberación oportuna de la memoria después de asignar la memoria a un objeto cuando el objeto ya no está en uso, lo que resulta en que la unidad de memoria esté ocupada y la memoria disponible real se reduce, al igual que una fuga de memoria.
Fugas de memoria causada por el método de subcadena
La subcadena (int beginIndex, int endndex) es un método de la clase de cadena, pero este método se implementa de manera completamente diferente en JDK6 y JDK7 (aunque ambos logran el mismo efecto). Comprender sus detalles de implementación puede ayudarlo a usarlos mejor, porque el uso inadecuado de la subcadena en JDK1.6 puede conducir a serios problemas de fuga de memoria.
1. El papel de la subcadena
El método subcandal (int BeginIndex, int EndIndex) devuelve una subcadena, que comienza desde el comienzo de la cadena principal y terminó en EndIndex-1. El subíndice de la cadena principal comienza en 0, y la subcadena contiene BeginIndex y no EndIndex
Cadena x = "abcdef"; x = str.substring (1,3); system.out.println (x);
La salida del programa anterior es "BC"
2. Principio de implementación
La clase de cadena es inmutable. Cuando X se reasigna en la segunda oración anterior, apuntará a un nuevo objeto de cadena. Sin embargo, no hay una descripción precisa o representa la situación real que ocurre en el montón. Lo que realmente sucede cuando se llama a la subcadena es la diferencia entre los dos.
Implementación de subcadena en JDK6
El objeto de cadena se almacena como una matriz de char. Hay 3 campos en la clase de cadena: Value Char [], int Offset e int Count, que se utilizan respectivamente para almacenar la matriz de caracteres real, la posición inicial de la matriz y el número de caracteres de la cadena. Estas 3 variables pueden determinar una cadena. Cuando se llama al método de subcadena, creará una nueva cadena, pero el valor de matriz de char anterior aún usará el valor de la matriz principal original. La única diferencia entre la matriz de padres e hijos es que los valores de recuento y desplazamiento son diferentes.
Eche un vistazo al código fuente de implementación de la subcadena en JDK6:
Public String Substring (int BeginIndex, int EndIndex) {if (beginIndex <0) {tire nuevo StringIndexOutofBoundSException (BeginIndex); } if (endIndex> count) {tire stringindexoUtofboundsexception (endIndex); } if (beginIndex> endIndex) {tire stringindexoUtofBoundsexception (endIndex - beginIndex); } return ((beginIndex == 0) && (endIndex == Count))? esto: nueva cadena (offset + beginIndex, endindex - beginIndex, valor); // se usa para usar el mismo valor de matriz de char que la cadena principal} String (int offset, int count, char valor []) {this.value = value; this.offset = offset; this.count = Count; }Cadena str = "abcdefghijklmnopqrst"; string sub = str.substring (1, 3); str = null;
Este programa simple tiene dos variables de cadena Str y Sub. La subcadena se obtiene por la cadena principal Str. Si el programa anterior se ejecuta en JDK1.6, sabemos que la asignación de espacio de memoria de la matriz se realiza en el montón, entonces el valor interno de matriz de carbón de SUB y STR es el mismo, es decir, la matriz de char anterior compuesta de caracteres como caracteres t. La única diferencia entre STR y SUM es la diferencia entre BeginIndex y el recuento de longitud del carácter en la matriz. En la tercera oración, hacemos vacío la referencia STR, que está destinada a liberar el espacio ocupado por STR, pero en este momento, GC no puede reciclar esta gran matriz de carbón porque todavía se hace referencia dentro de la subcadena, aunque SUB solo intercepta una pequeña parte de esta gran matriz. Cuando STR es una cuerda muy grande, este desperdicio es muy obvio e incluso puede provocar problemas de rendimiento. Puedes resolver este problema por:
Utiliza tecnología de empalme de cadena, que creará una nueva cadena. Esta nueva cadena utilizará una nueva matriz de caracteres internos para almacenar los caracteres que realmente necesita, de modo que la matriz de caracteres de la matriz principal no sea referenciada por otras fuentes. Str = NULL, y todo el espacio ocupado por STR se reciclará en la próxima vez que se recicle GC. Pero escribir así obviamente no es guapo, por lo que en JDK7, la subconjoce se vuelve a implementar.
Implementación de subcadena en JDK7
Implementación mejorada de la subcadena en JDK7, que en realidad crea una nueva matriz de char en el montón para las subcadenas interceptadas para mantener caracteres para las subcadenas.
Verifique el código fuente de implementación del método de subcadena de la clase de cadena en JDK7:
Public String Substring (int BeginIndex, int EndIndex) {if (beginIndex <0) {tire nuevo StringIndexOutofBoundSException (BeginIndex); } if (endIndex> value.length) {tire stringindexoUtofBoundsexception (endIndex); } int sublen = endindex - beginIndex; if (sublen <0) {arrojar nuevo StringIndexoUtofBoundSException (sublen); } return ((beginIndex == 0) && (endIndex == value.length))? esto: nueva cadena (valor, beginindex, sublen); } public String (Char valor [], int offset, int count) {if (offset <0) {tire stringindexoUtofBoundsexception (offset); } if (count <0) {arrojar nuevo StringInDexuToFboundSexception (Count); } // nota: el desplazamiento o el recuento pueden estar cerca de -1 >>> 1. if (offset> value.length - count) {tire nuevo StringInDexOutofBoundSException (offset + count); } this.value = arrays.copyOfRange (valor, desplazamiento, desplazamiento+recuento); }El método de CopyOfrange de la clase de matrices:
public static char [] copyOfrange (char [] original, int from, int to) {int newLength = to - from; if (newLength <0) tirar nueva ilegalargumentException (de + ">" + a); char [] copy = new Char [NewLength]; // es crear un nuevo sistema de matriz Char. devolver copia; }Se puede encontrar que se crea una nueva matriz de char para la subcadena para almacenar los caracteres en la subcadena. De esta manera, no existe una conexión necesaria entre la cadena infantil y la cadena principal. Cuando la referencia de la cadena principal no es válida, GC reciclará oportunamente el espacio de memoria ocupado por la cadena principal.
Resumir
Lo anterior es la explicación completa de la fuga de memoria causada por el método de subcadena en Java. Espero que sea útil para todos. Los amigos interesados pueden continuar referiéndose a otros temas relacionados en este sitio. Si hay alguna deficiencia, deje un mensaje para señalarlo. ¡Gracias amigos por su apoyo para este sitio!