В Java/Android есть четыре типа ссылок, а именно:
Сильная ссылка - сильная ссылка
Мягкая ссылка - мягкая ссылка
Слабая ссылка - слабая ссылка
Призрачная ссылка - виртуальная цитата
Различные эталонные типы имеют разные характеристики, а также соответствуют различным сценариям использования.
1. Встроенная ссылка - сильная ссылка
Наиболее распространенный тип ссылки в фактическом кодировании. Общие формы, такие как: a = new a (); и т. д. Сам сильная ссылка хранится в памяти стека, и он хранит адрес для объекта в памяти. Как правило, когда больше нет никакой сильной ссылки на объект в памяти, указывающий на него, машина сбора мусора начинает рассматривать коллекцию мусора, которая может быть сделана в этой памяти. Если кодирование: a = null, в настоящее время адрес, который был просто выделен в куче и созданном, не имеет других ссылок. Когда система выполняет сбор мусора, память кучи будет собрана мусором.
Softreference, SleaseReference и PhantomReference - все это подклассы класса java.lang.ref.reference. Ссылка, как абстрактный базовый класс, определяет основные операции своих объектов подкласса. Справочные подклассы имеют следующие характеристики:
1. Справочный подкласс не может быть создан непосредственно без параметризации. Он должен, по крайней мере, использовать сильный эталонный объект в качестве параметра конструкции для создания соответствующих объектов подкласса;
2. Поскольку объект создается в 1 с сильным эталонным объектом в качестве параметра конструкции, объекты в памяти кучи, на которые указывает первоначально сильную ссылку, больше не будут непосредственно связаны с самой сильной ссылкой, но также будут иметь определенное соединение со ссылкой на объект ссылки подкласса. И это соединение может повлиять на сбор мусора объекта.
В соответствии с различными характеристиками влияния различных подкласса объектов на сборку мусора их индикаторных объектов (прочные ссылки на объекты в памяти, на которые указаны), образуются три подкласса, а именно Softreference, SleaseReference и PhantomReference.
2. Справочник по сфере - мягкая ссылка
Форма общего использования мягкой ссылки заключается в следующем:
A = новый a ();
Softreference <a> sra = new softreference <a> (a);
Через сильную ссылку объекта в качестве параметра создается объект Softreference, а WRA в памяти стека указывает на этот объект.
В настоящее время выполняется следующая кодировка: a = null. Какое влияние он оказывает на сборку мусора объекта, на который первоначально указал А?
Давайте посмотрим на результаты вывода следующей программы:
Импорт java.lang.ref.softreference; открытый класс SERECTENCETEST {public static void main (string [] args) {a a = new a (); Softreference <a> sra = new softreference <a> (a); a = null; if (sra.get () == null) {System.out.println ("Объект входит в процесс сбора мусора"); } else {System.out.println ("объект еще не был переработан" + sra.get ()); } // System System.gc (); if (sra.get () == null) {System.out.println ("Объект входит в процесс сбора мусора"); } else {System.out.println ("объект еще не был переработан" + sra.get ()); }}} класс A {} ## Результат вывода:
1 объект не был переработан@4807ccf62 Объект не был переработан@4807ccf6
Когда a = null, объект A в памяти кучи больше не будет иметь никаких сильных ссылок на него, но есть модный объект, на который SRA, указывающий на объект A. Когда метод sra.get () вызывает впервые, чтобы вернуть этот объект индикатора, поскольку сборщик мусора, вероятно, еще не выполнил сборку мусора, в настоящее время get () имеет результат, который легко понять. Когда программа выполняет System.gc (); Принудительное сборы мусора, через sra.get (), обнаружено, что указанный объект все еще может быть получен, что указывает на то, что объект не был собран мусором. Итак, когда начнут собирать мусор, когда объекты, указанные в мягкой ссылке? Необходимо выполнить следующие два условия:
1. Когда объект, который он указывает, не имеет никакого сильного эталонного объекта, указывающего на него;
2. Когда у виртуальной машины недостаточно памяти.
Следовательно, Softreference расширяет время, что указывает на то, что объект занимает память кучи, пока у виртуальной машины не будет недостаточной памяти. Коллектор мусора не перерабатывает это пространство памяти кучи.
3. Ссылка на свидание - слабая ссылка
Точно так же форма общего использования мягкой ссылки заключается в следующем:
A = новый a ();
SleedReference <a> wra = new SleaseReference <a> (a);
Когда нет сильной ссылки, указывающей на этот объект, каковы характеристики сбора мусора?
Импорт java.lang.ref.weakreference; открытый класс Serfectestest {public static void main (string [] args) {a a = new a (); SleedReference <a> wra = new SleaseReference <a> (a); a = null; if (wra.get () == null) {System.out.println ("Объект входит в процесс сбора мусора"); } else {System.out.println ("Объект еще не был переработан" + wra.get ()); } // System System.gc (); if (wra.get () == null) {System.out.println ("Объект входит в процесс сбора мусора"); } else {System.out.println ("Объект еще не был переработан" + wra.get ()); }}} класс A {} ## Результат вывода:
Объект не был переработан, но объект@52E5376AA входит в процесс сбора мусора
Первый результат вывод объясняется, как указано выше. После сбора мусора WRA.Get () вернет NULL, указывая на то, что он указывает, что объект вошел в процесс сбора мусора. Следовательно, характеристики слабых цитат суммируются как:
ShideReference не меняет время сбора мусора исходного сильного эталонного объекта. Как только это указывает на то, что объект не имеет какого -либо сильного эталонного объекта, объект входит в обычный процесс сбора мусора.
Итак, основываясь на этой характеристике, есть вопрос: каково значение слабых зрителей?
Его основные сценарии использования: в настоящее время существуют сильные ссылки, указывающие на сильные эталонные объекты. В настоящее время, из -за потребностей бизнеса, необходимо увеличить ссылки на этот объект, и в то же время он не предназначен для изменения времени сбора мусора этой ссылки. В настоящее время ShideReference просто отвечает потребностям и обычно встречается в некоторых сценариях с жизненными циклами.
Ниже приведен сценарий для использования ShideReference в Android - сочетание статических внутренних классов и слабых обращений для решения возможной проблемы утечки памяти обработчика в деятельности.
В действии нам нужно создать новый поток для получения данных и использования метода Handler - Sendmessage. Вот общий код для этого процесса:
открытый класс MainActivity расширяет активность {// ... private int page; Private Handler Handler = new Handler () {@Override public void handlemessage (сообщение msg) {if (msg.what == 1) {// ... page ++; } еще { //... } }; }; @Override Protected void Oncreate (Bundle SavedInstanceState) {super.oncreate (savedInstanceState); setContentView (r.layout.activity_main); // ... новый поток (new Runnable () {@Override public void run () {// .. Сообщение msg = message.obtain (); msg.what = 1; //msg.obj = xx; handler.sendmessage (msg);}}). start (); // ...}}Запустите ссылку в Eclispe, вы увидите предупреждающее сообщение: этот класс обработчиков должен быть статичным, или могут возникнуть утечки ... Нажмите, чтобы просмотреть эту информацию, которая описывает проблему в деталях и предоставляет наводящее на мысль решение.
Проблема: гарантирует, что классы обработчиков не придерживаются ссылки на внешнюю классику: HandlerLeakSince Этот обработчик объявляется как внутренний класс, он может помешать собранному мусору. Если обработчик использует Looper или MessageQueue для потока, отличного от основного потока, то проблемы нет. Если обработчик использует Looper или MessageQueue основного потока, вам необходимо исправить объявление обработчика следующим образом: объявить обработчик статическим классом; во внешнем классе создать слабую ссылку на внешний класс и передать этот объект своему обработчику, когда вы создаете экземпляр обработчика; Сделайте все ссылки на членов внешнего класса, используя объект ShideReference.
Общее значение заключается в том, что рекомендуется определить обработчик как внутренний статический класс и определить ссылку на слабые версии в этом статическом внутреннем классе, из -за указания объекта внешней активности.
Анализ проблем:
Деятельность имеет свой жизненный цикл. Во время процесса работы вновь открытых потоков в деятельности пользователь может нажимать на клавишу с задней частью, или система недостаточно памяти и т. Д. Для переработки этой деятельности. Поскольку недавно запущенные потоки в деятельности не будут следовать циклу самой деятельности, то есть, когда деятельность выполняет Ondestroy, из-за существования потоков и ручного класса Handler, система изначально надеется выполнить восстановление памяти этого действия, поскольку невозможно реализовать проблемы с нестатическим классом, неявным образом придерживается ссылок на внешние классы, что приводит к возможным заменам памяти.
Следовательно, при использовании обработчика в активности, с одной стороны, его необходимо определить как статическая форма внутреннего класса, чтобы ее можно было отделить от внешнего класса и больше не иметь ссылок на внешний класс. В то же время, поскольку Handlermessage в обработчике обычно необходимо получить доступ или изменять свойства деятельности, в настоящее время, слабые звена, указывающие на эту деятельность, необходимо определить внутри обработчика, так что это не повлияет на восстановление памяти деятельности. В то же время, свойства деятельности можно получить при нормальных обстоятельствах.
Официальные рекомендации Google:
открытый класс MainActivity расширяет активность {// ... private int page; Частный Myhandler Mmyhandler = новый MyHandler (это); Частный статический класс MyHandler расширяет обработчик {private SleaseReference <mainActivity> Wractivity; public myHandler (MaterActivity Activity) {this.Wractivity = new SleaseReference <mainActivity> (Activity); } @Override public void handlemessage (сообщение 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 Runnable () {@Override public void run () {// .. Сообщение msg = message.obtain (); msg.what = 1; //msg.obj = xx; mmyhandler.sendmessage (msg);}}). start (); // ...}}Для Softreference и ShableReference также существует ссылка на параметр конструктора <T>, и когда объект, обозначенный Softreference или SleedReference, действительно собирается мусор, его ссылка будет помещена в REGINEBEUE. Обратите внимание, что, как указано выше, когда метод get () Softreference или SleadReference возвращает NULL, он только указывает на то, что объект, который он указывает, вступил в процесс сбора мусора, и объект, возможно, не был собран мусором в настоящее время. Только после подтверждения того, что он был собран мусором, если это ссылка, его ссылка будет размещена в справочнике.
См. Пример ниже:
открытый класс SERECTENCETEST {public static void main (string [] args) {a a = new a (); SleedReference <a> wra = new SleaseReference <a> (a); a = null; if (wra.get () == null) {System.out.println ("Объект входит в процесс сбора мусора"); } else {System.out.println ("Объект еще не был переработан" + wra.get ()); } // System System.gc (); if (wra.get () == null) {System.out.println ("Объект входит в процесс сбора мусора"); } else {System.out.println ("Объект еще не был переработан" + wra.get ()); }}} класс A {@Override Protected void inpintize () бросает throwable {super.finalize (); System.out.println («в окончательном языке»); }} ## Результат вывода:
1 Объект не был переработан@46993AAA2 объект был переработан 3 в завершении
Это также проверяет утверждение «Вступление в процесс сбора мусора», упомянутое выше. Давайте посмотрим на кусок кода в сочетании со ссылкой:
открытый класс SERECTENCETEST {public static void main (string [] args) {a a = new a (); Referencequeue <a> rq = new Referencequeue <a> (); ShideReference <a> wra = new SleaseReference <a> (a, rq); a = null; if (wra.get () == null) {System.out.println ("Объект входит в процесс сбора мусора"); } else {System.out.println ("Объект еще не был переработан" + wra.get ()); } System.out.println ("rq item:" + rq.poll ()); // Система сбора мусора.gc (); if (wra.get () == null) {System.out.println ("Объект входит в процесс сбора мусора"); } else {System.out.println ("Объект еще не был переработан" + wra.get ()); } /* try {thread.sleep (1000); } catch (прерванное искусство e) {e.printstacktrace (); } */ System.out.println ("rq item:" + rq.poll ()); }} класс A {@Override Protected void infintize () бросает throwable {super.finalize (); System.out.println («в окончательном языке»); }} ## Результат вывода:
Объект не был переработан, но@302b2c81rq. Пункт: Nulla Object входит в процесс сбора мусора RQ.
Таким образом, подтверждается, что «ссылки или слабые ссылки, которые вводят только процесс сбора мусора, не были добавлены в справочную эксплуатацию».
открытый класс SERECTENCETEST {public static void main (string [] args) {a a = new a (); Referencequeue <a> rq = new Referencequeue <a> (); ShideReference <a> wra = new SleaseReference <a> (a, rq); a = null; if (wra.get () == null) {System.out.println ("Объект входит в процесс сбора мусора"); } else {System.out.println ("Объект еще не был переработан" + wra.get ()); } System.out.println ("rq item:" + rq.poll ()); // Система сбора мусора.gc (); if (wra.get () == null) {System.out.println ("Объект входит в процесс сбора мусора"); } else {System.out.println ("Объект еще не был переработан" + wra.get ()); } try {thread.sleep (1); } catch (прерванное искусство e) {e.printstacktrace (); } System.out.println ("rq item:" + rq.poll ()); }} класс A {@Override Protected void infintize () бросает throwable {super.finalize (); System.out.println («в окончательном языке»); }} ## Результат вывода:
Объект не был переработан, но@6276e1dbrq.
Это подтверждает приведенное выше утверждение.
4. PhantomReference
По сравнению с Softreference или ShadeReference, основные различия в PhantomReference отражаются в следующих точках:
1. PhantomReference имеет только один конструктор PhantomReference (T Shorkse, RESTERKQUEUE <? SUPER T> Q), поэтому PhantomReference должен использоваться в сочетании с RetursQueue;
2. Независимо от того, существует ли сильная ссылка на объект индикатора, указывающий на PhantomReference, метод get () PhantomReference возвращает результат NULL.
открытый класс SERECTENCETEST {public static void main (string [] args) {a a = new a (); Referencequeue <a> rq = new Referencequeue <a> (); PhantomReference <a> pra = new PhantomReference <a> (a, rq); System.out.println ("pra.get ():" + pra.get ()); a = null; System.gc (); try {thread.sleep (1); } catch (прерванное искусство e) {e.printstacktrace (); } System.out.println ("rq item:" + rq.poll ()); }} класс A {} ## Результат вывода:
pra.get (): nullrq
Thread.sleep (1); В коде функционирует так же, как в приведенном выше примере, и оба убедитесь, что поток сбора мусора может выполняться. В противном случае, виртуальные ссылки на объект индикатора, который входит в процесс сбора мусора без фактического собрания мусора, не будут добавлены в PhantomReference.
Как и SleaseReference, PhantomReference не меняет время сбора мусора, указанного на его указанного объекта. Можно сделать вывод, что функция referenceaue в основном используется для прослушивания Softreference/SleaseReference/PhantomReference, указывающей, был ли объект был собран мусором.
Выше приведено полное содержание всестороннего анализа типов справочных данных Java/Android, принесенных вам редактором. Я надеюсь, что это будет полезно для вас и поддержать wulin.com больше ~