Pregunta

Fantasma Referencias sirven para post-mortem de las operaciones.La especificación de Java indica que un el fantasma de objeto de referencia no se desasigna hasta que el fantasma de referencia en sí es limpiado.

Mi pregunta es:¿Para qué sirve esta función (objeto no se desasigna) servir?

(La única idea que se me ocurrió, es permitir que el código nativo para hacer post-mortem de limpieza en el objeto, pero no es muy convincente).

¿Fue útil?

Solución

Lo único bueno de caso de uso que se me ocurre, que impediría la desasignación, es uno donde algún tipo de JNI-implementación del origen de datos asincrónica es escribir en el objeto de referencia, y debe ser contada a pie de la abajo - a dejar de escribir en el objeto antes de que la memoria es reciclado.Si antes de la desasignación se permitió, una simple olvidó a dispose() error podría resultar en la corrupción de memoria.

Este es uno de los casos en los que finalize (), que habría sido utilizado en el pasado, y probablemente condujo a algunas de sus peculiaridades.

Otros consejos

Edición, ya que he malinterpretar la pregunta primera:

Citado de aquí http://www.memorymanagement.org/glossary/p.html:

La especificación de Java dice que el el fantasma de referencia no se borra cuando el objeto de referencia es en la cola de espera, pero en realidad, no hay manera de que en el lenguaje para contar si ha sido hecho o no.En algunas implementaciones, JNI global débil, las referencias son más débiles que fantasma referencias, y proporcionar un forma de acceso fantasma accesible objetos.

Pero no he encontrado otras referencias que diría lo mismo.

Creo que la idea es dejar que los demás objetos extra de limpieza por encima y más allá de lo que el objeto original no.Por ejemplo, si el objeto original no puede ser extendida a implementar algunas de finalización de cosas, puedes utilizar fantasma de referencias.

El mayor problema es que la JVM no hace ninguna garantía de que un objeto siempre será finalizado, y supongo que por extensión no hay garantía de que el fantasma referencias llegar a hacer sus cosas post-finalización.

Fantasma de referencias puede ser utilizada para realizar la pre-recolección de basura acciones tales como la liberación de los recursos.En su lugar, la gente suele utilizar el finalize() método que no es una buena idea.Los finalizadores tiene un terrible impacto en el rendimiento del recolector de basura y se puede romper la integridad de los datos de la aplicación, si no eres muy cuidadoso, ya que la "finalizador" se invoca en una serie aleatoria de hilo, en un tiempo aleatorio.

En el constructor de un fantasma de referencia, se debe especificar un ReferenceQueue donde el fantasma de las referencias están en la cola de espera una vez que la referencia a objetos se convierte en "el fantasma alcanzable".Fantasma accesible significa inalcanzable de otra manera que por el fantasma de referencia.Inicialmente confuso cosa es que, aunque el fantasma de referencia continúa manteniendo el objeto de referencia en un campo privado (a diferencia de suave o débil referencias), su getReference() método siempre devuelve null.Esto es de modo que usted no puede hacer que el objeto fuertemente accesible de nuevo.

De vez en cuando, usted puede sondear la ReferenceQueue y comprobar si hay alguna nueva PhantomReferences cuya referencia a objetos se han convertido en fantasma accesible.Con el fin de ser capaz de cualquier cosa útil, uno puede, por ejemplo, derivar una clase de java.lang.ref.PhantomReference que hace referencia a los recursos que deben ser liberados antes de la recolección de basura.El objeto de referencia es sólo basura que se recoge una vez el fantasma de la referencia se convierte en inaccesible en sí.

http://www.javalobby.org/java/forums/m91822870.html#91822413

Esta es una solución perfecta para las Api de que no tienen un mecanismo de gestión del ciclo de vida, pero que se están implementando con algo que requiere explícita de la gestión del ciclo de vida.

En particular, cualquier tipo de API que se utiliza para sólo utilizar los objetos en memoria, pero que ha reimplantado el uso de una conexión de socket o archivo de conexión para algunos otros, mayor almacén de respaldo, puede utilizar PhantomReference a "cerrar" y la limpieza de la información de la conexión antes de que el objeto de ser GC d y la conexión nunca se cierra porque no había gestión del ciclo de vida de la API de interfaz que se puede utilizar de otra manera.

Pensar en mudarse a un simple Mapa de mapa en una base de datos.Cuando el mapa de referencia se descarta, no es explícito "cerrar la operación".Sin embargo, si se había puesto en marcha una escritura a través de la caché, le gustaría ser capaz de terminar cualquier escribe y cerrar el socket de conexión a la su "base de datos".

A continuación es una clase que yo uso para este tipo de cosas.Tenga en cuenta, que las Referencias a PhantomReferences debe ser no-referencias locales para que funcione correctamente.De lo contrario, el jit hará que ellos se pongan en cola prematuramente antes de salir de los bloques de código.

    import java.lang.ref.PhantomReference;
    import java.lang.ref.Reference;
    import java.lang.ref.ReferenceQueue;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.logging.Level;
    import java.util.logging.Logger;

    /**
     * This class provides a way for tracking the loss of reference of one type of
     * object to allow a secondary reference to be used to perform some cleanup
     * activity.  The most common use of this is with one object which might
     * contain or refer to another object that needs some cleanup performed
     * when the referer is no longer referenced.
     * 

* Un ejemplo podría ser un objeto de tipo Titular, que se refiere a o utiliza un * Conexión de Socket.Cuando la referencia se pierde, la toma debe ser * cerrado.Por lo tanto, un ejemplo podría ser creado como en *

     *    ReferenceTracker trker = ReferenceTracker() {
     *        public void released( Socket s ) {
     *            try {
     *                s.close();
     *            } catch( Exception ex ) {
     *                log.log( Level.SEVERE, ex.toString(), ex );
     *            }
     *        }
     *  };
     * 
* Somewhere, there might be calls such as the following. *
     *        interface Holder {
     *            public T get();
     *        }
     *        class SocketHolder implements Holder {
     *            Socket s;
     *            public SocketHolder( Socket sock ) {
     *                s = sock;
     *            }
     *            public Socket get() {
     *                return s;
     *            }
     *        }
     * 
* This defines an implementation of the Holder interface which holds * a reference to Socket objects. The use of the trker * object, above, might then include the use of a method for creating * the objects and registering the references as shown below. *
     *    public SocketHolder connect( String host, int port ) throws IOException {
     *        Socket s = new Socket( host, port );
     *        SocketHolder h = new SocketHolder( s );
     *        trker.trackReference( h, s );
     *        return h;
     *    }
     * 
* Software wishing to use a socket connection, and pass it around would * use SocketHolder.get() to reference the Socket instance, in all cases. * then, when all SocketHolder references are dropped, the socket would * be closed by the released(java.net.Socket) method shown * above. *

* El {@link ReferenceTracker} clase utiliza un {@link PhantomReference} para el primer argumento como * la clave de un mapa de mantener una referencia al segundo argumento.Por lo tanto, cuando el * clave instancia se libera, la referencia clave está en la cola, que puede ser eliminado de * la cola, y se utiliza para quitar el valor a partir del mapa que se pasa a continuación a * liberado().*/ public abstract class ReferenceTracker { /** * El hilo de la instancia que es la eliminación de las entradas de la referencia de la cola, refqueue, tal y como aparecen.*/ privado volátiles RefQueuePoll encuesta;/** * El Registrador instancia utilizado para esta instancia.Se incluirá el nombre, como un sufijo * si el constructor se utiliza.*/ private static final del Registrador de registro = Registrador.getLogger(ReferenceTracker.clase.getName());/** * El nombre, lo que indica que esta instancia es para el registro y otras separación de * las instancias necesarias.*/ private final String;/** * Crea una nueva instancia de ReferenceTracker utilizando el pasado nombre para diferenciar * la instancia en el registro y el método toString() de la aplicación.* @param que El nombre de esta instancia para la diferenciación de varias instancias en el registro, etc.*/ público ReferenceTracker( Cadena ) { este.que = que;} /** * Crea una nueva instancia de ReferenceTracker sin clasificación nombre.*/ público ReferenceTracker( ) { este.que = null;} /** * Proporciona acceso a el nombre de esta instancia.* @return El nombre de esta instancia.*/ @Override public String toString() { if( cual == null ) { return super.toString()+":ReferenceTracker";} return super.toString()+":ReferenceTracker["+cual+"]";} /** * Las subclases deben implementar este método.Será llamado cuando todas las referencias a la * asociado titular objeto se deja caer.* @param val El valor que se pasa como segundo argumento para una llamada correspondiente a {@link #trackReference(Objeto) trackReference(T,K)} */ public abstract void liberado( K val );/** La referencia de la cola para las referencias a los objetos de titular */ la final privado ReferenceQueuerefqueue = new ReferenceQueue();/** * El recuento del número total de hilos que se han creado y destruido como entradas tienen * seguimiento realizado.Cuando hay cero seguimiento de referencias, no hay cola de ejecución.*/ la final privado AtomicInteger tcnt = new AtomicInteger();privado volátiles booleano ejecución;/** * Un Hilo de ejecución que las encuestas {@link #refqueue} para posteriormente llamar a {@link liberado(K)} * como referencias a T objetos se caen.*/ clase privada RefQueuePoll extends Thread { /** * El número de subprocesos asociados con esta instancia.Allí brevemente podría haber dos instancias de * esta clase que existe en un sistema volátil.Si ese es el caso, este valor se * ser visible en algunos de los registro para diferenciar los activos.*/ private final int mycnt;/** * Crea una instancia de esta clase.*/ público RefQueuePoll() { setDaemon( true );setName( getClass().getName()+":ReferenceTracker ("+cual+")" );mycnt = tcnt.incrementAndGet();} /** * Este método proporciona toda la actividad de la realización de refqueue.remove() * llamadas y, a continuación, llamar a released(K) dejar que la versión de la aplicación de la * recursos necesarios.*/ público @Override void run() { try { doRun();} catch( Arrojadiza ex ) { registro.log( hecho ?Level.INFO :Nivel.GRAVE, ex.toString()+":fantasma ref encuesta hilo de detener", ex );} finally { ejecutando = false;} } privado volátiles booleano hecho = false;private void doRun() { while( !done ) { Referencia ref = null;try { ejecutando = true;ref = refqueue.remove();K ctl;sincronizado( refmap ) { ctl = refmap.quitar( ref );hecho = actCnt.decrementAndGet() == 0;if( registro.isLoggable( de Nivel.FINE ) ) { registro.log(Level.FINE "de la ley actual ref={0}, mapsize={1}", new Object[]{actCnt.get(), refmap.size()});} si( actCnt.get() != refmap.size() ) { Arrojar ex = new IllegalStateException("la cuenta de referencias activas y tamaño del mapa no están en sintonía");registro.log(Level.GRAVE, ex.toString(), ex);} } if( registro.isLoggable( de Nivel.Más FINO ) ) { registro.log(Level.Más FINO, "de referencia publicado por:{0}, dep={1}", new Object[]{ref, ctl});} si( ctl != null ) { try { liberado( ctl );if( registro.isLoggable( de Nivel.FINE ) ) { registro.log(Level.BIEN", dependiente del objeto lanzado:{0}", ctl);} } catch( RuntimeException ex ) { registro.log( Level.GRAVE, ex.toString(), ex );} } } catch( Exception ex ) { registro.log( Level.GRAVE, ex.toString(), ex );} finally { si( ref != null ) { ref.clear();} } } if( registro.isLoggable( de Nivel.FINE ) ) { registro.log(Level.BIEN, "encuesta hilo {0} cierre de {1}", new Object[]{mycnt, este});} } } /** * Un recuento de las referencias activas.*/ la final privado AtomicInteger actCnt = new AtomicInteger();/** * Mapa de T Referencias a los K objetos para ser utilizados para la libertad(K) de la llamada */ la final privado ConcurrentHashMap,K>refmap = new ConcurrentHashMap,K>();/** * Añade un seguimiento de referencia.dep no debe referirse a ref en cualquier forma, excepto, posiblemente, * WeakReference.dep es casi siempre algo que se refiere ref.* @throws IllegalArgumentException de ref y dep son el mismo objeto.* @param dep El objeto dependiente que necesita la limpieza cuando ref se deja de hacer referencia.* @param ref el objeto cuya referencia es ser rastreado */ public void trackReference( T ref, K dep ) { si( ref == dep ) { throw new IllegalArgumentException( "objeto de Referencia y dependiente del objeto no puede ser el mismo" );} PhantomReference p = new PhantomReference( ref, refqueue );sincronizado( refmap ) { refmap.put( p, dep );si( actCnt.getAndIncrement() == 0 || se ejecuta == false ) { si( actCnt.get() > 0 && ejecutando == false ) { if (registro.isLoggable(de Nivel.FINE)) { registro.fine("a partir de detenido fantasma ref sondeo de hilo");} } encuesta = new RefQueuePoll();en la encuesta.start();if( registro.isLoggable( de Nivel.FINE ) ) { registro.log( Level.BIEN, "encuesta de hilo #{0} creado para {1}", new Object[]{tcnt.get(), este});} } } } /** * Este método puede ser llamado si la JVM que el tracker está en, se * apagar, o someother contexto se cierre y el seguimiento de objetos * por el tracker ahora debe ser puesto en libertad.Este método resultará en * {@link #publicado(Objeto) liberado(K) } se llama a cada una de referencia.*/ public void shutdown() { Listrem;// Copia los valores y limpiar el mapa de modo que se publicaron // solo se llama una vez, en caso de GC más tarde le desaloja referencias sincronizado( refmap ) { rem = new ArrayList( refmap.los valores de() );refmap.clear();} para( K dep :rem ) { try { liberado( dep );} catch( Exception ex ) { registro.log( Level.GRAVE, ex.toString(), ex );} } } }

Puede permitir que ustedes dos han fantasma cachés que son muy eficientes en la gestión de la memoria.Simplemente, si usted tiene enormes objetos que son difíciles de crear, pero rara vez se usa, se puede utilizar un fantasma caché para hacer referencia a ellos y asegúrese de que no consumen la memoria que es más valioso.Si el uso regular de referencias que tiene que ser manualmente asegúrese de que no hay referencias a la izquierda para el objeto.Se puede argumentar de la misma sobre cualquier objeto, pero usted no tiene que administrar manualmente las referencias en el fantasma de la caché.Sólo tienes que ser cuidadoso para comprobar si han sido recogidos o no.

También puede utilizar un marco de trabajo (es decir,una fábrica), donde las referencias se dan como fantasma referencias.Esto es útil si los objetos son muchos y de corta duración (es decir,utiliza y luego se eliminan).Muy útil para limpiar la memoria si ha descuidado a los programadores que piensan que la recolección de basura es mágico.

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