# è°è°å¼ºå¼ç¨ã软å¼ç¨ãå¼±å¼ç¨ã幻象å¼ç¨ * [è°è°å¼ºå¼ç¨ã软å¼ç¨ãå¼±å¼ç¨ã幻象å¼ç¨](#è°è°å¼ºå¼ç¨è½¯å¼ç¨å¼±å¼ç¨å¹»è±¡å¼ç¨) * [åè¯å¼ç¨](#åè¯å¼ç¨) * [å徿¶éå¨](#å徿¶éå¨) * [Finalizers](#finalizers) * [对象ççå½å¨æ](#对象ççå½å¨æ) * [ReferenceQueue](#referencequeue) * [Reference](#reference) æä»¬è¯´çä¸åçå¼ç¨ç±»åå ¶å®é½æ¯é»è¾ä¸çï¼è对äºèææºæ¥è¯´ï¼ä¸»è¦ä½ç°çæ¯å¯¹è±¡çä¸åç`å¯è¾¾æ§(reachable)` ç¶æå对`å徿¶é(garbage collector)`çå½±åã ## åè¯å¼ç¨ 对äºåæ¥è§¦ Java ç C++ ç¨åºåèè¨ï¼çè§£æ åå çå ³ç³»å¯è½å¾ä¸ä¹ æ¯ãå¨ C++ ä¸ï¼å¯ä»¥ä½¿ç¨ new æä½ç¬¦å¨å ä¸åå»ºå¯¹è±¡ï¼æè 使ç¨èªå¨åé 卿 ä¸å建对象ãä¸é¢ç C++ è¯å¥æ¯åæ³çï¼ä½æ¯ Java ç¼è¯å¨å´æç»è¿ä¹å代ç ï¼ä¼åºç° `syntax error` ç¼è¯é误ã ```java Integer foo = Integer(1); ``` Java å C ä¸ä¸æ ·ï¼Java ä¸ä¼æå¯¹è±¡é½æ¾å¨å ä¸ï¼éè¦ new æä½ç¬¦æ¥åå»ºå¯¹è±¡ãæ¬å°åéåå¨å¨`æ `ä¸ï¼å®ä»¬ææä¸ä¸ªæåå ä¸å¯¹è±¡ç`å¼ç¨(æé)`ãä¸é¢æ¯ä¸ä¸ª Java æ¹æ³ï¼è¯¥æ¹æ³å ·æä¸ä¸ª Integer åéï¼è¯¥åéä» String è§£æå¼ ```java public static void foo(String bar){ Integer baz = new Integer(bar); } ``` è¿æ®µä»£ç æä»¬ä½¿ç¨å æ åé å¾å¯ä»¥çä¸ä¸å®ä»¬çå ³ç³»  é¦å å æ¥çä¸ä¸ `foo()` æ¹æ³ï¼è¿ä¸è¡ä»£ç åé äºä¸ä¸ªæ°ç Integer 对象ï¼JVM å°è¯å¨å 空é´ä¸å¼è¾ä¸åå å空é´ã妿å 许åé çè¯ï¼å°±ä¼è°ç¨ Integer çæé æ¹æ³æ String å符串转æ¢ä¸º Integer 对象ãJVM å°æå该对象çæéåå¨å¨åé baz ä¸ã ä¸é¢è¿ç§æ 嵿¯æä»¬ä¹æçå°çæ åµï¼æ¯ç«æä»¬ä¸æ³å¨ç¼å代ç çæ¶åéå°é»ç¢ï¼ä½æ¯è¿ç§æ 嵿¯ä¸å¯è½åºç°çï¼å½å ç©ºé´æ æ³ä¸º bar å baz å¼è¾å åç©ºé´æ¶ï¼å°±ä¼åºç° `OutOfMemoryError`ï¼ç¶åå°±ä¼è°ç¨`å徿¶éå¨(garbage collector)` æ¥å°è¯è ¾åºå å空é´ãè¿ä¸é´æ¶åå°ä¸ä¸ªé®é¢ï¼å徿¶éå¨ä¼åæ¶åªäºå¯¹è±¡ï¼ ## å徿¶éå¨ Java ç»ä½ æä¾äºä¸ä¸ª new æä½ç¬¦æ¥ä¸ºå ä¸ç对象å¼è¾å å空é´ï¼ä½å®æ²¡ææä¾ `delete` æä½ç¬¦æ¥éæ¾å¯¹è±¡ç©ºé´ãå½ foo() æ¹æ³è¿åæ¶ï¼å¦æåé baz è¶ è¿æå¤§å åï¼ä½å®ææåç对象ä»ç¶è¿å¨å ä¸ãå¦ææ²¡æåå¾åæ¶å¨çè¯ï¼é£ä¹ç¨åºå°±ä¼æåº `OutOfMemoryError` é误ãç¶è Java ä¸ä¼ï¼å®ä¼æä¾å徿¶é卿¥éæ¾ä¸åå¼ç¨ç对象ã å½ç¨åºå°è¯å建æ°å¯¹è±¡å¹¶ä¸å 䏿²¡æè¶³å¤çç©ºé´æ¶ï¼å徿¶éå¨å°±å¼å§å·¥ä½ã彿¶éå¨è®¿é®å æ¶ï¼è¯·æ±çº¿ç¨è¢«æèµ·ï¼è¯å¾æ¥æ¾ç¨åºä¸å主å¨ä½¿ç¨ç对象ï¼å¹¶åæ¶å®ä»¬ç空é´ã妿å徿¶é卿 æ³éæ¾è¶³å¤çå å空é´ï¼å¹¶ä¸JVM æ æ³æ©å±å ï¼åä¼åºç° `OutOfMemoryError`ï¼ä½ çåºç¨ç¨åºé常å¨è¿ä¹åå´©æºãè¿æä¸ç§æ 嵿¯ `StackOverflowError` ï¼å®åºç°çåå æ¯å 为线ç¨è¯·æ±çæ æ·±åº¦è¦å¤§äºèææºæå è®¸çæ·±åº¦æ¶åºç°çé误ã ###æ è®° - æ¸ é¤ç®æ³ Java è½æ°¸ä¹ ä¸è¡°çä¸ä¸ªåå å°±æ¯å 为å徿¶éå¨ã许å¤äººè®¤ä¸º JVM ä¼ä¸ºæ¯ä¸ªå¯¹è±¡ä¿çä¸ä¸ªå¼ç¨è®¡æ°ï¼å½æ¯æ¬¡å¼ç¨å¯¹è±¡çæ¶åï¼å¼ç¨è®¡æ°å¨çå¼å°± + 1ï¼å½å¼ç¨å¤±æçæ¶åï¼å¼ç¨è®¡æ°å¨çå¼å°± - 1ãèå徿¶éå¨åªä¼åæ¶å¼ç¨è®¡æ°å¨çå¼ä¸º 0 çæ åµãè¿å ¶å®æ¯ `å¼ç¨è®¡æ°æ³(Reference Counting)` çæ¶éæ¹å¼ã使¯è¿ç§æ¹å¼æ æ³è§£å³å¯¹è±¡ä¹é´ç¸ä¼å¼ç¨çé®é¢ï¼å¦ä¸ ```java class A{ public B b; } class B{ public A a; } public class Main{ public static void main(String[] args){ A a = new A(); B b = new B(); a.b=b; b.a=a; } } ``` ç¶èå®é ä¸ï¼JVM 使ç¨ä¸ç§å«å `æ è®°-æ¸ é¤(Mark-Sweep)`çç®æ³ï¼æ è®°æ¸ é¤åå¾åæ¶èåçæ³æ³å¾ç®åï¼ç¨åºæ æ³å°è¾¾çæ¯ä¸ªå¯¹è±¡é½æ¯åå¾ï¼å¯ä»¥è¿è¡åæ¶ã æ è®°-æ¸ é¤æ¶éå ·æå¦ä¸å ä¸ªé¶æ®µ * é¶æ®µä¸ï¼æ è®° å徿¶éå¨ä¼ä» `æ ¹(root)` å¼ç¨å¼å§ï¼æ è®°å®å°è¾¾çææå¯¹è±¡ã妿ç¨èå¸ç»å¦ç夿å·åæ¥æ¯å»ï¼è¿å°±ç¸å½äºæ¯ç»è¯å·ä¸çå ¨é¨çæ¡å¤ææ£ç¡®è¿æ¯é误çè¿ç¨ã  * é¶æ®µäºï¼æ¸ ç å¨ç¬¬ä¸é¶æ®µä¸ææå¯åæ¶ççå 容é½è½å¤è¢«å徿¶éå¨è¿è¡åæ¶ã妿ä¸ä¸ªå¯¹è±¡è¢«å¤å®ä¸ºæ¯å¯ä»¥åæ¶ç对象ï¼é£ä¹è¿ä¸ªå¯¹è±¡å°±è¢«æ¾å¨ä¸ä¸ª `finalization queue(åæ¶éå)`ä¸ï¼å¹¶å¨ç¨åä¼ç±ä¸ä¸ªèææºèªå¨å»ºç«çãä½ä¼å 级ç `finalizer` 线ç¨å»æ§è¡å®ã  * é¶æ®µä¸ï¼æ´çï¼å¯éï¼ ä¸äºæ¶éå¨æç¬¬ä¸ä¸ªæ¥éª¤ï¼æ´çãå¨è¿ä¸ªæ¥éª¤ä¸ï¼GC å°å¯¹è±¡ç§»å¨å°å徿¶éå¨åæ¶å®å¯¹è±¡åæçä¸çèªç±ç©ºé´ä¸ãè¿ä¹åå¯ä»¥é²æ¢å ç¢çåï¼é²æ¢å¤§å¯¹è±¡å¨å ä¸ç±äºå 空é´çä¸è¿ç»æ§èæ æ³åé çæ åµã  æä»¥ä¸é¢çè¿ç¨ä¸å°±æ¶åå°ä¸ä¸ª`æ ¹èç¹(GC Roots)` æ¥å¤ææ¯å¦åå¨éè¦åæ¶ç对象ãè¿ä¸ªç®æ³çåºæ¬ææ³å°±æ¯éè¿ä¸ç³»åç `GC Roots` ä½ä¸ºèµ·å§ç¹ï¼ä»è¿äºèç¹åä¸æç´¢ï¼æç´¢æèµ°è¿çè·¯å¾ç§°ä¸º `å¼ç¨é¾(Reference Chain)`ï¼å½ä¸ä¸ªå¯¹è±¡å° GC Roots ä¹é´æ²¡æä»»ä½å¼ç¨é¾ç¸è¿çè¯ï¼åè¯ææ¤å¯¹è±¡ä¸å¯ç¨ãå¼ç¨é¾ä¸çä»»ä½ä¸ä¸ªè½å¤è¢«è®¿é®çå¯¹è±¡é½æ¯`强å¼ç¨` 对象ï¼å徿¶éå¨ä¸ä¼åæ¶å¼ºå¼ç¨å¯¹è±¡ã å æ¤ï¼è¿åå° foo() æ¹æ³ä¸ï¼ä» 卿§è¡æ¹æ³æ¶ï¼åæ° bar åå±é¨åé baz ææ¯å¼ºå¼ç¨ã䏿¦æ¹æ³æ§è¡å®æï¼å®ä»¬é½è¶ è¿äºä½ç¨åçæ¶åï¼å®ä»¬å¼ç¨ç对象é½ä¼è¿è¡åå¾åæ¶ã ä¸é¢æ¥èèä¸ä¸ªä¾å ```java LinkedList foo = new LinkedList(); foo.add(new Integer(111)); ``` åé foo æ¯ä¸ä¸ªå¼ºå¼ç¨ï¼å®æåä¸ä¸ª LinkedList 对象ãLinkedListï¼JDK.18ï¼ æ¯ä¸ä¸ªé¾è¡¨çæ°æ®ç»æï¼æ¯ä¸ä¸ªå ç´ é½ä¼æåå驱å ç´ ï¼æ¯ä¸ªå ç´ é½æå ¶åç»§å ç´ ã  彿们è°ç¨`add()` æ¹æ³æ¶ï¼æä»¬ä¼å¢å ä¸ä¸ªæ°çé¾è¡¨å ç´ ï¼å¹¶ä¸è¯¥é¾è¡¨å ç´ æåå¼ä¸º 111 ç Integer å®ä¾ãè¿æ¯ä¸è¿ä¸²ç强å¼ç¨ï¼ä¹å°±æ¯è¯´ï¼è¿ä¸ª Integer çå®ä¾ä¸ç¬¦åå徿¶éæ¡ä»¶ã䏿¦ foo å¯¹è±¡è¶ åºäºç¨åºè¿è¡çä½ç¨åï¼LinkedList åå ¶ä¸çå¼ç¨å 容é½å¯ä»¥è¿è¡æ¶éï¼æ¶éçåææ¯æ²¡æå¼ºå¼ç¨å ³ç³»ã ### Finalizers C++ å 许对象å®ä¹ææå½æ°æ¹æ³ï¼å½å¯¹è±¡è¶ åºä½ç¨èå´æè¢«æç¡®å 餿¶ï¼ä¼è°ç¨ææå½æ°æ¥æ¸ ç使ç¨çèµæºã对äºå¤§å¤æ°å¯¹è±¡æ¥è¯´ï¼ææå½æ°è½å¤éæ¾ä½¿ç¨ new æè malloc 彿°åé çå åã å¨Javaä¸ï¼å徿¶éå¨ä¼ä¸ºä½ èªå¨æ¸ é¤å¯¹è±¡ï¼åé å åï¼å æ¤ä¸éè¦æ¾å¼ææå½æ°å³å¯æ§è¡æ¤æä½ãè¿ä¹æ¯ Java å C++ çä¸å¤§åºå«ã ç¶èï¼å å并䏿¯å¯ä¸éè¦è¢«éæ¾çèµæºãèè `FileOutputStream`ï¼å½ä½ å建æ¤å¯¹è±¡çå®ä¾æ¶ï¼å®ä»æä½ç³»ç»åé æä»¶å¥æãå¦æä½ è®©æµçå¼ç¨å¨å ³éåè¶ è¿äºå ¶ä½ç¨èå´ï¼è¯¥æä»¶å¥æä¼æä¹æ ·ï¼å®é ä¸ï¼æ¯ä¸ªæµé½ä¼æä¸ä¸ª `finalizer` æ¹æ³ï¼è¿ä¸ªæ¹æ³æ¯åå¾åæ¶å¨å¨åæ¶ä¹åç± JVM è°ç¨çæ¹æ³ãå¯¹äº FileOutputStream æ¥è¯´ï¼**finalizer æ¹æ³ä¼å ³éæµï¼éæ¾æä»¶å¥æç»æä½ç³»ç»ï¼ç¶åæ¸ é¤ç¼å²åºï¼ç¡®ä¿æ°æ®è½å¤åå ¥ç£ç**ã ä»»ä½å¯¹è±¡é½å ·æ finalizer æ¹æ³ï¼ä½ è¦åçå°±æ¯å£°æ `finalize()` æ¹æ³ãå¦ä¸ ```java protected void finalize() throws Throwable { // æ¸ é¤å¯¹è±¡ } ``` è½ç¶ finalizers ç finalize() æ¹æ³æ¯ä¸ç§å¥½çæ¸ é¤æ¹å¼ï¼ä½æ¯è¿ç§æ¹æ³äº§ççè´é¢å½±åé常大ï¼ä½ ä¸åºè¯¥ä¾é è¿ä¸ªæ¹æ³æ¥åä»»ä½åå¾åæ¶å·¥ä½ãå 为 `finalize` æ¹æ³çè¿è¡å¼éæ¯è¾å¤§ï¼ä¸ç¡®å®æ§å¼ºï¼æ æ³ä¿è¯å个对象çè°ç¨é¡ºåºãfinalize è½åçä»»ä½äºæ ï¼å¯ä»¥ä½¿ç¨ `try-finally` æè å ¶ä»æ¹å¼æ¥åï¼çè³åçæ´å¥½ã ## 对象ççå½å¨æ ç»¼ä¸æè¿°ï¼å¯ä»¥éè¿ä¸é¢çæµç¨æ¥å¯¹å¯¹è±¡ççå½å¨æåä¸ä¸ªæ»ç»  对象被å建并åå§åï¼å¯¹è±¡å¨è¿è¡æ¶è¢«ä½¿ç¨ï¼ç¶å离å¼å¯¹è±¡çä½ç¨åï¼å¯¹è±¡ä¼åæä¸å¯è¾¾å¹¶ä¼è¢«å徿¶éå¨åæ¶ãå¾ä¸ç¨çº¢è²æ æçåºå表示对象å¤äºå¼ºå¯è¾¾é¶æ®µã JDK1.2 ä»ç»äº `java.lang.ref` å ï¼å¯¹è±¡ççå½å¨ææåä¸ªé¶æ®µï¼`ô²§å¼ºå¯è¾¾ô°(Strongly Reachableô°)`ã`软å¯è¾¾(Soft Reachableô°)`ã`å¼±å¯è¾¾(Weak Reachableô°)`ã `幻象å¯è¾¾(Phantom Reachableô°)`ã  妿åªè®¨è®ºç¬¦ååå¾åæ¶æ¡ä»¶ç对象ï¼é£ä¹åªæä¸ç§ï¼è½¯å¯è¾¾ãå¼±å¯è¾¾å幻象å¯è¾¾ã * 软å¯è¾¾ï¼è½¯å¯è¾¾å°±æ¯ô±¬æä»¬åªè½éè¿è½¯å¼ç¨ô³æè½è®¿é®çç¶æï¼è½¯å¯è¾¾ç对象æ¯ç± `SoftReference` å¼ç¨ç对象ï¼å¹¶ä¸æ²¡æå¼ºå¼ç¨ç对象ã软å¼ç¨æ¯ç¨æ¥æè¿°ä¸äºè¿**æç¨ä½æ¯éå¿ é¡»**ç对象ãå徿¶éå¨ä¼å°½å¯è½é¿æ¶é´çä¿ç软å¼ç¨ç对象ï¼ä½æ¯ä¼å¨åç `OutOfMemoryError` ä¹åï¼åæ¶è½¯å¼ç¨ç对象ã妿忶å®è½¯å¼ç¨ç对象ï¼å åè¿æ¯ä¸å¤åé çè¯ï¼å°±ä¼ç´æ¥æåº OutOfMemoryErrorã * å¼±å¯è¾¾ï¼å¼±å¯è¾¾çå¯¹è±¡æ¯ `WeakReference` å¼ç¨ç对象ãå徿¶éå¨å¯ä»¥éæ¶æ¶éå¼±å¼ç¨ç对象ï¼ä¸ä¼å°è¯ä¿ç软å¼ç¨ç对象ã * 幻象å¯è¾¾ï¼å¹»è±¡å¯è¾¾æ¯ç± `PhantomReference ` å¼ç¨ç对象ï¼å¹»è±¡å¯è¾¾å°±æ¯æ²¡æå¼ºã软ãå¼±å¼ç¨è¿è¡å ³èï¼å¹¶ä¸å·²ç»è¢« finalize è¿äºï¼åªæå¹»è±¡å¼ç¨æåè¿ä¸ªå¯¹è±¡çæ¶åã 餿¤ä¹å¤ï¼è¿æå¼ºå¯è¾¾åä¸å¯è¾¾ç两ç§å¯è¾¾æ§å¤ææ¡ä»¶ * 强å¯è¾¾ï¼å°±æ¯ä¸ä¸ªå¯¹è±¡å被å建ãåå§åã使ç¨ä¸çå¯¹è±¡é½æ¯å¤äºå¼ºå¯è¾¾çç¶æ * `ä¸å¯è¾¾(unreachable)`ï¼å¤äºä¸å¯è¾¾ç对象就æå³ç对象å¯ä»¥è¢«æ¸ é¤äºã ä¸é¢æ¯ä¸ä¸ªä¸åå¯è¾¾æ§ç¶æç转æ¢å¾  夿å¯è¾¾æ§æ¡ä»¶ï¼ä¹æ¯ JVM å徿¶éå¨å³å®å¦ä½å¤ç对象çä¸é¨åèèå ç´ ã ææç对象å¯è¾¾æ§å¼ç¨é½æ¯ `java.lang.ref.Reference` çåç±»ï¼å®é颿ä¸ä¸ª`get()` æ¹æ³ï¼è¿åå¼ç¨å¯¹è±¡ã 妿已éè¿ç¨åºæå徿¶é卿¸ é¤äºæ¤å¼ç¨å¯¹è±¡ï¼åæ¤æ¹æ³è¿å null ãä¹å°±æ¯è¯´ï¼é¤äºå¹»è±¡å¼ç¨å¤ï¼è½¯å¼ç¨åå¼±å¼ç¨é½æ¯å¯ä»¥å¾å°å¯¹è±¡çãèä¸è¿äºå¯¹è±¡å¯ä»¥äººä¸º`æ¯æ`ï¼å为强å¼ç¨ï¼ä¾å¦æ this å ³é®åèµå¼ç»å¯¹è±¡ï¼åªè¦éæ°åå¼ç¨é¾ä¸çä»»æä¸ä¸ªå¯¹è±¡å»ºç«å ³èå³å¯ã ### ReferenceQueue `å¼ç¨éå`å称为 `ReferenceQueue`ï¼å®ä½äº java.lang.ref å ä¸ãæä»¬å¨ô°å»ºåç§å¼ç¨ï¼è½¯å¼ç¨ï¼å¼±å¼ç¨ï¼å¹»è±¡å¼ç¨ï¼å¹¶å ³èå°ååºå¯¹è±¡ô°æ¶ï¼å¯ä»¥éæ©æ¯å¦éè¦å ³èå¼ç¨éåãJVM ä¼å¨ç¹å®çæ¶æºå°å¼ç¨å ¥éå°éåä¸ï¼ç¨åºå¯ä»¥éè¿å¤æå¼ç¨éå䏿¯å¦å·²ç»å å ¥å¼ç¨ï¼æ¥äºè§£è¢«å¼ç¨ç对象æ¯å¦è¢«GCåæ¶ã ### Reference java.lang.ref.Reference 为软ï¼softï¼å¼ç¨ãå¼±ï¼weakï¼å¼ç¨ãèï¼phantomï¼å¼ç¨çç¶ç±»ãå 为 Reference 对象ååå¾åæ¶å¯åé åå®ç°ï¼è¯¥ç±»å¯è½ä¸è½è¢«ç´æ¥åç±»åã  