Pregunta

Esperemos que una pregunta simple. Tomemos, por ejemplo, una lista enlazada circularmente:

class ListContainer
{
  private listContainer next;
  <..>

  public void setNext(listContainer next)
  {
    this.next = next;
  }
}

class List
{
  private listContainer entry;
  <..>
}

Ahora, dado que se trata de una lista enlazada circularmente, cuando se agrega un elemento único, tiene una referencia a sí mismo en su siguiente variable. Al eliminar el único elemento de la lista, la entrada se establece en nulo. ¿Es necesario configurar ListContainer.next como nulo también para que el Garbage Collector libere su memoria o maneja esas auto-referencias de forma automática?

¿Fue útil?

Solución

Los recolectores de basura que se basan únicamente en el recuento de referencias son generalmente vulnerables a la falta de recopilación de estructuras autorreferenciales como esta. Estos GC se basan en un recuento del número de referencias al objeto para calcular si un objeto determinado es alcanzable.

Los enfoques de conteo sin referencia aplican una prueba de accesibilidad más completa para determinar si un objeto es elegible para ser recolectado. Estos sistemas definen un objeto (o conjunto de objetos) que siempre se asume que son alcanzables. Cualquier objeto para el cual las referencias están disponibles en este gráfico de objeto se considera inelegible para la colección. Cualquier objeto al que no se pueda acceder directamente desde este objeto no lo es. Por lo tanto, los ciclos no terminan afectando la accesibilidad, y pueden ser recolectados.

Vea también, la página de Wikipedia en rastreo de recolectores de basura .

Otros consejos

Las referencias circulares son un problema (solucionable) si confía en contar las referencias para decidir si un objeto está muerto. Ninguna implementación de java usa el conteo de referencias, AFAIK. Los nuevos Sun JREs utilizan una mezcla de varios tipos de GC, creo que todos marcan y barren o copian.

Puede leer más sobre la recolección de basura en general en Wikipedia , y algunos artículos sobre java GC aquí y aquí , por ejemplo.

La respuesta real a esto depende de la implementación. Sun JVM realiza un seguimiento de algunos conjuntos de objetos raíz (subprocesos y similares), y cuando necesita hacer una recolección de basura, rastrea los objetos a los que se puede acceder y los guarda, descartando el resto. En realidad, es más complicado que eso permitir algunas optimizaciones, pero ese es el principio básico. Esta versión no se preocupa por las referencias circulares: siempre que ningún objeto vivo contenga una referencia a uno muerto, puede ser GCed.

Otras JVM pueden usar un método conocido como conteo de referencias. Cuando se crea una referencia al objeto, se incrementa un contador, y cuando la referencia queda fuera del alcance, el contador disminuye. Si el contador llega a cero, el objeto se finaliza y se recolecta la basura. Esta versión, sin embargo, permite la posibilidad de referencias circulares que nunca se recolectarán como basura. Como medida de seguridad, muchas de estas JVM incluyen un método de copia de seguridad para determinar qué objetos realmente están muertos, lo que se ejecuta periódicamente para resolver las auto-referencias y desfragmentar el montón.

Dejando de lado la no respuesta (las respuestas existentes son más que suficientes), es posible que desee consultar un documento técnico sobre el sistema de recolección de basura de JVM si está interesado en GC. (Cualquier, solo google JVM Garbage Collection)

Me sorprendieron algunas de las técnicas utilizadas y, al leer algunos de los conceptos, como "Eden", Realmente me di cuenta por primera vez que Java y JVM en realidad podían superar a C / C ++ en velocidad. (Cada vez que C / C ++ libera un objeto / bloque de memoria, el código está involucrado ... Cuando Java libera un objeto, en realidad no hace nada en absoluto; ya que en un buen código OO, la mayoría de los objetos se crean y liberan casi de inmediato. esto es increíblemente eficiente.)

Los GC modernos tienden a ser muy eficientes, ya que administran los objetos más antiguos de manera muy diferente a los nuevos, ya que pueden controlar los GC para que sean cortos y semidesnudos o largos y completos, y muchas opciones de GC se pueden administrar con los interruptores de la línea de comando por lo que es realmente útil saber a qué se refieren realmente todos los términos.

Nota: Me acabo de dar cuenta de que esto era engañoso. La asignación STACK de C ++ es muy rápida; mi punto fue sobre la asignación de objetos que pueden existir después de que la rutina actual haya terminado (lo que creo que DEBERÍA ser todos los objetos) es algo en lo que no debería tener que pensar si va a piense en OO, pero en C ++ la velocidad puede hacer esto poco práctico).

Si solo estás asignando clases de C ++ en la pila, la asignación será al menos tan rápida como la de Java.

Java recopila cualquier objeto que no sea accesible. Si nada más tiene una referencia a la entrada, se recopilará, aunque tenga una referencia a sí mismo.

sí, auto-referencia del recolector de basura de Java!

How?

Hay objetos especiales llamados raíces de recolección de basura (raíces GC). Estos son siempre accesibles y también lo es cualquier objeto que los tenga en su propia raíz.

Una aplicación Java simple tiene las siguientes raíces GC:

  1. Variables locales en el método principal
  2. El hilo principal
  3. Variables estáticas de la clase principal

ingrese la descripción de la imagen aquí

Para determinar qué objetos ya no están en uso, la JVM ejecuta de forma intermitente lo que se denomina muy bien un algoritmo de marcar y barrer . Funciona de la siguiente manera

  1. El algoritmo atraviesa todas las referencias de objetos, comenzando con el GC Raíces, y marca cada objeto encontrado como vivo.
  2. Toda la memoria del montón que no está ocupada por objetos marcados es regenerado. Simplemente se marca como libre, esencialmente libre de objetos no utilizados.

Por lo tanto, si no se puede acceder a ningún objeto desde las raíces de GC (incluso si se hace referencia a sí mismo o tiene una referencia cíclica), será sujeto a la recolección de basura.

Simplemente, sí. :)

Consulte http://www.ibm.com/developerworks/ java / library / j-jtp10283 /

Todos los JDK (de Sun) tienen un concepto de "capacidad de alcance". Si el GC no puede " alcanzar " Un objeto, se va.

Esto no es ningún " nuevo " Información (los primeros en responder son excelentes), pero el enlace es útil y la brevedad es algo dulce. :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top