2010-05-28 16 views
47

Ayúdame a resolver una disputa con un compañero de trabajo: ¿Tiene establecimiento de una variable o una colección de nula en ayuda de Java en la recolección de basura y reducir el uso de memoria? Si tengo un programa en ejecución largo y cada función puede ser llamado de forma iterativa (potencialmente miles de veces): ¿El ajuste de todas las variables en ella a nula antes de devolver un valor a la función de ayuda de los padres reducir el uso de tamaño de la pila/tarjeta de memoria?variable = SET NULL para la recolección de basura

+4

+1 Buena pregunta. – CoolBeans

Respuesta

57

Eso es viejo saber rendimiento. Fue cierto en 1.0 días, pero el compilador y la JVM se han mejorado para eliminar la necesidad (si alguna vez hubo uno). Este excelente artículo de IBM entra en detalles si está interesado: Java theory and practice: Garbage collection and performance

+0

+1: Es un gran artículo y el tipo de munición que estaba buscando. – ashurexm

+0

El enlace estaba roto. Corrija el enlace. –

+0

El artículo aún se puede encontrar en http://web.archive.org. Ver: http://web.archive.org/web/20130928235110/http://www.ibm.com/developerworks/java/library/j-jtp01274/index.html –

3

No necesariamente. Un objeto se vuelve elegible para la recolección de basura cuando ya no hay subprocesos activos que contienen una referencia al objeto.

Las variables locales salen del alcance cuando el método retorna y no tiene ningún sentido establecer las variables locales en nulo - las variables desaparecen de todos modos, y si no hay nada más que contenga una referencia de los objetos a los que se refieren las variables, entonces esos objetos se vuelven elegibles para la recolección de basura.

La clave es no mirar sólo las variables, pero mira los objetos que esas variables se refieren a, y averiguar donde los objetos son referenciados por su programa.

2

No es útil en variables locales, pero puede ser útil/necesario para borrar variables de instancia que ya no son necesarias (por ejemplo, post-inicialización).

(Sí, sí, sé cómo aplicar el Builder ...)

+0

** Puede ** ser útil en varibles locales, si el compilador no puede resolverlo, no se volverá a leer la varible. En la mayoría de los casos, el compilador ** puede ** resolverlo por sí mismo. –

+0

@IanRingrose La pregunta es sobre anular antes de la salida del procedimiento. La práctica es inútil. El compilador no participa en la recolección de basura. – EJP

-4

Es un bueno tener. Cuando establece los objetos como nulos, existe la posibilidad de que el objeto pueda ser recogido más rápidamente, en el ciclo GC inmediato. Pero no hay un mecanismo garantizado para hacer que un objeto sea recogido en un momento dado.

+0

Puede ser una buena idea en ciertos casos especiales, pero ciertamente no siempre debes establecer las variables en 'nulo' (nótese que es importante ser preciso: no puedes" poner objetos a nulo ") por costumbre, sin pensar .Eso lleva a una especie de programación supersticiosa, donde no sabes por qué estás haciendo cosas, lo cual es una mala idea. – Jesper

+0

La pregunta es sobre anular antes de devolver, y es una pérdida de tiempo. – EJP

5

El Java VM Spec

12.6.1 La implementación Finalización Cada objeto se puede caracterizar por dos atributos: puede ser alcanzable, finalizador alcanzable, o inalcanzable, y también puede ser no finalizado, finalizables, o finalizado

Un objeto alcanzable es cualquier objeto al que se pueda acceder en cualquier cálculo continuo potencial desde cualquier hilo en vivo. Se pueden diseñar transformaciones de optimización de un programa que reduzcan la cantidad de objetos accesibles para que sean inferiores a los que ingenuamente se considerarían alcanzables. Por ejemplo, un generador de compilador o código puede optar por configurar una variable o parámetro que ya no se utiliza en null para hacer que el almacenamiento de un objeto tal como potencialmente recuperable antes.

Discusión

Otro ejemplo de esto se produce si los valores de los campos de un objeto se almacenan en registros. El programa puede entonces acceder a los registros en lugar del objeto, y nunca volver a acceder al objeto. Esto implicaría que el objeto es basura.

El objeto es alcanzable si puede estar involucrado en cualquier posible cálculo continuo. Por lo tanto, si su código hace referencia a una variable local y no se refiere a nada más, puede hacer que el objeto se recopile configurándolo como nulo. Esto daría una excepción de puntero nulo o cambiaría el comportamiento de su programa, o si no lo hace, no necesita la variable en primer lugar.

Si está anulando un campo o un elemento de matriz, puede tener sentido para algunas aplicaciones y hará que la memoria se reclame más rápido. Una vez que Case está creando una gran matriz para reemplazar una matriz existente referenciada por un campo en una clase, si el campo en nulled antes de la sustitución se crea, entonces puede aliviar la presión sobre la memoria.

Otra característica interesante de Java es que el alcance no aparece en los archivos de clase, por lo que el alcance no es relevante para la accesibilidad; estos dos métodos crean el mismo código de bytes, y por lo tanto la máquina virtual no ve el alcance del objeto creado en absoluto:

static void withBlock() { 
    int x = 1; 

    { 
     Object a = new Object(); 
    } 

    System.out.println(x+1); 
} 

static void withoutBlock() { 
    int x = 1; 

    Object a = new Object(); 

    System.out.println(x+1); 
} 
1

que sólo podía hacer algunos sentido en algún escenario como este:

public void myHeavyMethod() { 
    List hugeList = loadHugeListOfStuff(); // lots of memory used 
    ResultX res = processHugeList(hugeList); // compute some result or summary 
    // hugeList = null; // we are done with hugeList 
    ... 
    // do a lot of other things that takes a LOT of time (seconds?) 
    // and which do not require hugeList 
    ... 
} 

Aquí podría hacer algún beneficio para descomentar la línea hugeList = null, supongo.

Pero ciertamente tendría más sentido reescribir el método (tal vez refactorizar en dos, o especificar un alcance interno).

+1

Solo si la VM no implementa la versión 3 de la especificación de JVM. –

+0

podrías elaborar? – leonbloy

+0

Lea la cita en mi respuesta sobre accesibilidad. Si processHughList no almacena una referencia al objeto al que hace referencia la lista enorme, entonces no se puede acceder en ningún cálculo continuo potencial a partir de ningún hilo activo y, por lo tanto, es inalcanzable y, por lo tanto, elegible para la recolección de basura. Si processHughList solo usa el tamaño y la matriz de datos (asumiendo que List es similar a una ArrayList) y estos fueron JITted como variables de registro, entonces el objeto incluso podría ser recolectado antes de que processHughList regrese. –

7

Desde el artículo:

Hay un caso en el que el uso de anulación explícita no sólo es útil, pero prácticamente se requiera, y que es donde está en el ámbito de una referencia a un objeto de manera más amplia de lo que se usa o considerado válido por las especificaciones del programa. Esto incluye casos como el uso de un campo estático o de instancia para almacenar una referencia a un búfer temporal, en lugar de una variable local, o el uso de una matriz para almacenar referencias que pueden permanecer accesibles por el tiempo de ejecución pero no por la semántica implícita del programa.

Traducción: objetos persistentes "explícitamente nulos" que ya no son necesarios. (Si lo desea, "¿Es prácticamente necesario?" Una afirmación demasiado fuerte?)

0

Establecer una referencia de objeto nulo solo lo hace elegible para recolección de basura. No libera necesariamente la memoria, que depende de cuándo se ejecuta el recolector de elementos no utilizados (que depende de JVM). Cuando se ejecuta el recolector de elementos no utilizados, libera el montón al eliminar solo los objetos que son elegibles para la recolección de elementos no utilizados.

Cuestiones relacionadas