Hay cuatro tipos de referencia en Java/Android, a saber:
Referencia fuerte - referencia fuerte
Referencia suave - Referencia suave
Referencia débil - referencia débil
Referencia Phantom - Cita virtual
Diferentes tipos de referencia tienen diferentes características y también corresponden a diferentes escenarios de uso.
1. Referencia de estruenización - referencia fuerte
El tipo de referencia más común en la codificación real. Formas comunes tales como: a a = new a (); etc. La fuerte referencia en sí misma se almacena en la memoria de la pila, y almacena la dirección al objeto en la memoria. En general, cuando ya no hay ninguna referencia fuerte al objeto en la memoria que le apunta, la máquina de recolección de basura comienza a considerar la recolección de basura que podría hacerse en esta memoria. Si codifica: a = nulo, en este momento, la dirección que se asignó en el montón y creó no tiene otras referencias. Cuando el sistema realiza la recolección de basura, la memoria del montón se recolectará basura.
Softreference, WeakReference y Phantomreference son todas las subclases de la clase java.lang.ref.reference. La referencia, como clase base abstracta, define las operaciones básicas de sus objetos de subclase. Las subclases de referencia tienen las siguientes características:
1. La subclase de referencia no se puede crear directamente sin parametrización. Al menos debe usar el objeto de referencia fuerte como parámetro de construcción para crear sus respectivos objetos de subclase;
2. Debido a que el objeto se crea en 1 con el objeto de referencia fuerte como el parámetro de construcción, los objetos en la memoria del montón apuntan por la referencia originalmente fuerte ya no estarán directamente relacionadas con la referencia fuerte en sí, pero también tendrán una cierta conexión con la referencia del objeto de referencia de subclase. Y esta conexión puede afectar la recolección de basura del objeto.
De acuerdo con las diferentes características de influencia de los diferentes objetos de subclase en la recolección de basura de sus objetos indicadores (fuertes referencias a objetos en la memoria de almacenamiento de almacenamiento puntual), se forman tres subclases, a saber, Softreference, WeakReference y Phantomreference.
2. Referencia de software - Referencia suave
La forma de uso general de referencia suave es la siguiente:
A a a = nuevo a ();
Softreference <a> sra = new Softreference <a> (a);
A través de la fuerte referencia del objeto como parámetro, se crea un objeto Softreference y el WRA en los puntos de memoria de pila a este objeto.
En este momento, se realiza la siguiente codificación: a = nulo. ¿Qué impacto tiene en la recolección de basura del objeto que un apuntado originalmente por A?
Echemos un vistazo a los resultados de la salida del siguiente programa:
import java.lang.ref.softreference; public class referenceTest {public static void main (string [] args) {a a = new a (); Softreference <a> sra = new Softreference <a> (a); a = nulo; if (sra.get () == null) {system.out.println ("Un objeto ingresa al proceso de recolección de basura"); } else {System.out.println ("Un objeto aún no se ha reciclado" + sra.get ()); } // System.gc (); if (sra.get () == null) {system.out.println ("Un objeto ingresa al proceso de recolección de basura"); } else {System.out.println ("Un objeto aún no se ha reciclado" + sra.get ()); }}} clase A {} ## El resultado de la salida es:
1 Un objeto no ha sido reciclado como@4807CCF62 Un objeto no se ha reciclado como un@4807ccf6
Cuando a = nulo, el objeto A en la memoria del montón ya no tendrá referencias fuertes a él, pero hay un objeto de moda a la que se hace referencia a SRA que apunta al objeto A. Cuando el método sra.get () se requiere por primera vez para devolver este objeto indicador, ya que es probable que el recolector de basura aún no haya realizado la recolección de basura, Get () tiene un resultado en este momento, lo cual es fácil de entender. Cuando el programa ejecuta System.gc (); Al forzar la recolección de basura, a través de sra.get (), se encuentra que el indicado aún se puede obtener un objeto, lo que indica que el objeto A no se ha recolectado basura. Entonces, ¿cuándo los objetos indicados por la referencia suave comenzarán a ser recolectados de basura? Se deben cumplir las siguientes dos condiciones:
1. Cuando el objeto que indica no tiene ningún objeto de referencia fuerte que le apunte;
2. Cuando la máquina virtual tiene memoria insuficiente.
Por lo tanto, Softreference extiende el tiempo que indica que el objeto ocupa la memoria del montón hasta que la máquina virtual tenga memoria insuficiente. El recolector de basura no recicla este espacio de memoria de montón.
3. Referencia de Weak - Referencia débil
Del mismo modo, la forma de uso general de referencia suave es la siguiente:
A a a = nuevo a ();
Débilreference <a> wra = new WeakReference <a> (a);
Cuando no hay una referencia fuerte que apunte a este objeto, ¿cuáles son sus características de recolección de basura?
import java.lang.ref.weakreference; public class referenceTest {public static void main (string [] args) {a a = new a (); Débilreference <a> wra = new WeakReference <a> (a); a = nulo; if (wra.get () == null) {system.out.println ("Un objeto ingresa al proceso de recolección de basura"); } else {System.out.println ("Un objeto aún no se ha reciclado" + wra.get ()); } // System.gc (); if (wra.get () == null) {system.out.println ("Un objeto ingresa al proceso de recolección de basura"); } else {System.out.println ("Un objeto aún no se ha reciclado" + wra.get ()); }}} clase A {} ## El resultado de la salida es:
Un objeto aún no se ha reciclado un objeto@52e5376aa que ingresa al proceso de recolección de basura
La primera salida del resultado se explica como arriba. Después de la recolección de basura, wra.get () devolverá nulo, lo que indica que indica que el objeto ha ingresado al proceso de recolección de basura. Por lo tanto, las características de las citas débiles se resumen como:
WeakReference no cambia el momento de la recolección de basura del objeto de referencia fuerte original. Una vez que indica que el objeto no tiene ningún objeto de referencia fuerte, el objeto ingresa al proceso normal de recolección de basura.
Entonces, según esta característica, hay una pregunta: ¿cuál es el significado de la referencia débil?
Sus principales escenarios de uso son: actualmente hay referencias fuertes que apuntan a objetos de referencia fuertes. En este momento, debido a las necesidades comerciales, es necesario aumentar las referencias a este objeto y, al mismo tiempo, no pretende cambiar el momento de la recolección de basura de esta referencia. En este momento, WeakReference simplemente satisface las necesidades y se encuentra comúnmente en algunos escenarios con ciclos de vida.
El siguiente es un escenario para el uso de la referencia débil en Android, que combina clases internas estáticas y una referencia débil para resolver el posible problema de fuga de memoria del controlador en la actividad.
En la actividad, necesitamos crear un nuevo hilo para obtener datos y usar el controlador de controlador - SendMessage. Aquí está el código general para este proceso:
La clase pública MainActivity extiende la actividad {// ... Private int página; Handler de controlador privado = new Handler () {@Override public void HandLemessage (Mensaje Msg) {if (msg.what == 1) {// ... página ++; } demás { //... } }; }; @Override protegido void onCreate (Bundle SaveDInStancestate) {super.oncreate (saveDInStancestate); setContentView (r.layout.activity_main); // ... New Thread (new runnable () {@Override public void run () {// .. Message msg = message.obtain (); msg.what = 1; //msg.obj = xx; handler.sendMessage (msg);}}). start (); // ...}}Ejecute el enlace en Eclispe, verá un mensaje de advertencia: esta clase de controlador debe ser estática o puede ocurrir fugas ... haga clic para ver esta información, que describe el problema en los detalles y proporciona una solución sugerente.
Problema: Asegura que las clases de controladores no se aferren a una referencia a un Classid externo: HandlerLeaks desde que este controlador se declara como una clase interna, puede evitar que la clase exterior sea recolectada de basura. Si el controlador está usando un looper o un mensaje de mensajes para un hilo que no sea el hilo principal, entonces no hay problema. Si el controlador está utilizando el looper o el mensaje de mensajes del hilo principal, debe arreglar su declaración de controlador, de la siguiente manera: declare el controlador como una clase estática; en la clase externa, instanciar una referencia débil a la clase externa y pasar este objeto a su controlador cuando instancea el controlador; Haga todas las referencias a los miembros de la clase externa utilizando el objeto WeakReference.
El significado general es que se recomienda definir el controlador como una clase estática interna, y definir una referencia a la referencia débil en esta clase interna estática, debido a que indica el objeto de actividad externa.
Análisis de problemas:
La actividad tiene su propio ciclo de vida. Durante el proceso de ejecución de los hilos recién abiertos en la actividad, el usuario puede presionar la tecla Atrás o el sistema es una memoria insuficiente, etc. para reciclar esta actividad. Debido a que los hilos recién lanzados en la actividad no seguirán el ciclo de la actividad en sí, es decir, cuando la actividad ejecuta a OnDestrOY, debido a la existencia de hilos y la mano manual del manejo, el sistema originalmente espera realizar la recuperación de la memoria de esta actividad, porque la clase interna no estadística implica las referencias a las clases externas, lo que resulta en posibles problemas de fuga de memoria.
Por lo tanto, al usar el controlador en la actividad, por un lado, debe definirse como una forma de clase interna estática, para que pueda desacoplarse de la clase externa y ya no tener referencias a la clase externa. Al mismo tiempo, dado que el manual en el controlador generalmente necesita acceder o modificar las propiedades de la actividad, en este momento, la referencia débil que apunta a esta actividad debe definirse dentro del controlador para que no afecte la recuperación de la memoria de la actividad. Al mismo tiempo, se puede acceder a las propiedades de la actividad en circunstancias normales.
Las recomendaciones oficiales de Google son:
La clase pública MainActivity extiende la actividad {// ... Private int página; privado myhandler mmyhandler = nuevo myhandler (esto); Clase estática privada MyHandler extiende Handler {Private WeakReference <MainActivity> Wractivity; public MyHandler (Actividad de MainActivity) {this.wractivity = new WeakReference <MainActivity> (Actividad); } @Override public void HandLemessage (Mensaje msg) {if (wractivity.get () == null) {return; } MainActivity mActivity = wractivity.get (); if (msg.what == 1) {// ... mActivity.page ++; } else {// ...}}} @Override Protected void onCreate (Bundle SavedInStancestate) {super.oncreate (saveDInStanceState); setContentView (r.layout.activity_main); // ... new Thread (new runnable () {@Override public void run () {// .. Message msg = message.obtain (); msg.what = 1; //msg.obj = xx; mmyhandler.sendMessage (msg);}}). start (); // ...}}Para Softreference y WeakReference, también hay una referencia de parámetros constructoras <t>, y cuando el objeto indicado por Softreference o WeakReference se recolecte basura, su referencia se colocará en la referencia de referencia. Tenga en cuenta que como se indicó anteriormente, cuando el método get () de Softreference o WeakReference devuelve nulo, solo indica que el objeto que indica ha ingresado al proceso de recolección de basura, y el objeto puede no haber sido recolectado en este momento. Solo después de confirmar que ha sido recolectado de basura, si la referencia lo es, su referencia se colocará en referencequeue.
Vea un ejemplo a continuación:
clase pública referenceTest {public static void main (string [] args) {a a = new a (); Débilreference <a> wra = new WeakReference <a> (a); a = nulo; if (wra.get () == null) {system.out.println ("Un objeto ingresa al proceso de recolección de basura"); } else {System.out.println ("Un objeto aún no se ha reciclado" + wra.get ()); } // System.gc (); if (wra.get () == null) {system.out.println ("Un objeto ingresa al proceso de recolección de basura"); } else {System.out.println ("Un objeto aún no se ha reciclado" + wra.get ()); }}} Clase A {@Override Proteged Void Finalize () lanza Throwable {super.Finalize (); System.out.println ("en una finalización"); }} ## El resultado de la salida es:
1 Un objeto no ha sido reciclado como un@46993aaa2 Se ha reciclado un objeto 3 en una finalización
Esto también verifica la declaración "Entrando en el proceso de recolección de basura" mencionada anteriormente. Veamos un código de código en combinación con referenceQueue:
clase pública referenceTest {public static void main (string [] args) {a a = new a (); ReferenceQueue <a> rq = new RefectionQueue <a> (); Débilreference <a> wra = new WeakReference <a> (a, rq); a = nulo; if (wra.get () == null) {system.out.println ("Un objeto ingresa al proceso de recolección de basura"); } else {System.out.println ("Un objeto aún no se ha reciclado" + wra.get ()); } System.out.println ("RQ item:" + rq.poll ()); // System.gc (); if (wra.get () == null) {system.out.println ("Un objeto ingresa al proceso de recolección de basura"); } else {System.out.println ("Un objeto aún no se ha reciclado" + wra.get ()); } /* try {thread.sleep (1000); } catch (InterruptedException e) {E.PrintStackTrace (); } */ System.out.println ("RQ item:" + rq.poll ()); }} Clase A {@Override Proteged Void Finalize () lanza Throwable {super.Finalize (); System.out.println ("en una finalización"); }} ## El resultado de la salida es:
Aún no se ha reciclado un objeto un elemento@302b2c81rq: el objeto nulla ingresa al proceso de recolección de basura RQ Artículo: NULLIN A FINALIZE
Por lo tanto, se verifica que "Softreference o WeakReference referencias que ingresan solo el proceso de recolección de basura no se han agregado a Referencequeue".
clase pública referenceTest {public static void main (string [] args) {a a = new a (); ReferenceQueue <a> rq = new RefectionQueue <a> (); Débilreference <a> wra = new WeakReference <a> (a, rq); a = nulo; if (wra.get () == null) {system.out.println ("Un objeto ingresa al proceso de recolección de basura"); } else {System.out.println ("Un objeto aún no se ha reciclado" + wra.get ()); } System.out.println ("RQ item:" + rq.poll ()); // System.gc (); if (wra.get () == null) {system.out.println ("Un objeto ingresa al proceso de recolección de basura"); } else {System.out.println ("Un objeto aún no se ha reciclado" + wra.get ()); } try {thread.sleep (1); } catch (InterruptedException e) {E.PrintStackTrace (); } System.out.println ("RQ item:" + rq.poll ()); }} Clase A {@Override Proteged Void Finalize () lanza Throwable {super.Finalize (); System.out.println ("en una finalización"); }} ## El resultado de la salida es:
Aún no se ha reciclado un objeto un elemento@6276e1dbrq: el objeto nulla ingresa al proceso de recolección de basura en un elemento de finalizadorq: java.lang.ref.weakreference@645064f
Esto confirma la declaración anterior.
4.phantomreference
En comparación con Softreference o WeakReference, las principales diferencias en la fantomreferencia se reflejan en los siguientes puntos:
1. Phantomreference tiene solo un constructor Phantomreference (t reference, referencequeue <? Super t> q), por lo que la fantasma debe usarse en combinación con referenceQueue;
2. Independientemente de si existe una fuerte referencia al objeto indicador que apunta a Phantomreference, el método get () de Phantomreference devuelve el resultado nulo.
clase pública referenceTest {public static void main (string [] args) {a a = new a (); ReferenceQueue <a> rq = new RefectionQueue <a> (); Phantomreference <a> pra = new Phantomreference <a> (a, rq); System.out.println ("pra.get ():" + pra.get ()); a = nulo; System.gc (); intente {Thread.sleep (1); } catch (InterruptedException e) {E.PrintStackTrace (); } System.out.println ("RQ item:" + rq.poll ()); }} Clase A {} ## El resultado de la salida es:
pra.get (): NULLRQ Artículo: java.lang.ref.phantomreference@1da12fc0
El hilo.sleep (1); En el código funciona lo mismo que en el ejemplo anterior, y ambos se aseguran de que el hilo de recolección de basura pueda ejecutar. De lo contrario, las referencias virtuales al objeto indicador que ingresan al proceso de recolección de basura sin ser recolectados de basura no se agregarán a la fantomreferencia.
Al igual que la referencia débil, Phantomreference no cambia el momento de la recolección de basura de su objeto indicador. Se puede concluir que la función de referenceQueue se usa principalmente para escuchar el Softreference/WeakReference/Phantomreference que indica si el objeto ha sido recolectado de basura.
Lo anterior es el contenido completo del análisis exhaustivo de los tipos de referencia de Java/Android y el uso que le ofrece el editor. Espero que sea útil para usted y apoye a Wulin.com más ~