咱們知道,動態代理(這裏指JDK的動態代理)與靜態代理的區別在於,其真實的代理類是動態生成的。但具體是怎麼生成,生成的代理類包含了哪些內容,以什麼形式存在,它爲何必定要以接口爲基礎?javascript
若是去看動態代理的源代碼(java.lang.reflect.Proxy
),會發現其原理很簡單(真正二進制類文件的生成是在本地方法中完成,源代碼中沒有),但其中用到了一個緩衝類java.lang.reflect.WeakCache<ClassLoader, Class<?>[], Class<?>>
,這個類用到了弱引用來構建。java
在JDK的3個特殊引用中,弱引用是使用範圍最廣的,它的特性也最清晰,相對而言,其餘兩種邏輯稍顯晦澀,源碼中的註釋也語焉不詳。本文將簡單介紹幾種引用的行爲特徵,而後分析一下弱引用的一些實際應用場景,其中包含了動態代理中的實現。本文將包含如下內容:ios
Java的全部運行邏輯都是基於引用的,其形態相似於不可變的指針,因此在Java中會有一些很繞的概念,好比說, Java中函數的傳參是值傳遞,但這裏所說的值,實際上是引用的值,因此你能夠經過一個函數的參數來修改其對象的值。另外一方面,Java中還存在一些基本數據類型,它們沒有引用,傳遞的是真實的值,因此不能在函數內部修改參數的值。npm
關於引用,Java中有這樣幾種:api
全部對象的引用默認爲強引用,普通代碼中,賦值語句之間傳遞的都是強引用,若是一個對象能夠被某個線程(活着的,下同)經過強引用訪問到,則稱之爲強可達的(Strongly Reachable)。瀏覽器
強可達的對象不會被GC回收。緩存
當一個對象不是強可達的,但能夠被某個線程經過軟引用訪問到,則稱之爲軟可達的(Softly Reachable)。app
軟可達的對象的引用只有在內存不足時會被清除,使之能夠被GC回收。在這一點上,JVM是不保證具體何時清除軟引用,但能夠保證在OOM以前會清除軟可達的對象。同時,JVM也不保證軟可達的對象的回收順序,但Oracle JDK的文檔中提到,最近建立和最近使用的軟可達對象每每會最後被回收,與LRU相似。dom
當一個對象不是強可達的,也不是軟可達的,但能夠被某個線程經過弱引用訪問到,則稱之爲弱可達的(Weakly Reachable)。jvm
弱引用是除了強引用以外,使用最普遍的引用類型,它的特性也更簡單,當一個對象是弱可達時,JVM就會清除這個對象上的弱引用,隨後對這個對象進行回收動做。
當一個對象,經過以上幾種可達性分析都不可達,且已經finalized,但有虛引用指向它,則它是虛可達的(Phantom Reachable)。
虛引用是行爲最詭異,使用方法最難的引用,後邊會講到。
虛引用不會影響GC,它的get()方法永遠返回null,惟一的用處就是在GC finalize一個對象以後,它會被放到指定的隊列中去。關於這個隊列會在下邊說明。
JVM的GC經過可達性分析來判斷一個對象是否可被回收,其基本思路就是以GC Roots爲起點遍歷鏈路上全部對象,當一個對象和GC Roots之間沒有任何的直接或間接引用相連時,就稱之爲不可達對象,則證實此對象是不可用的。
而進一步,Java中又定義瞭如上所述的4種不一樣的可達性,用來實現更精細的GC策略。
對於普通的強引用對象,若是其變成不可達以後,一般GC會進行Finalize(Finalize主要目的是讓用戶能夠自定義釋放資源的過程,一般是釋放本地方法中使用的資源),而後將它的對象銷燬回收,但對於本文中討論的3種引用,還有可能在這個過程當中作一些別的事情:
GC根據約定的規則來決定是否清除這些引用
這方面上一節已經講過了,每一個引用類型都有約定的處理規則。
若是它們註冊了引用隊列,在Finalize對象後,將引用的對象放入隊列。
主要用來使開發者能夠獲得對象被銷燬的通知,固然,如虛引用這樣的,其引用不會自動被清除,因此它能夠阻止其所引用的對象被回收。
java.lang.ref.Reference<T>
)對象的狀態這裏所說的「引用對象」指的是由類
java.lang.ref.Reference<T>
生產的對象,這個對象上保持了「須要特殊處理的」對「目標對象」的引用。
引用對象有4種狀態,根據它與其註冊的隊列的關係,分爲如下4種:
Active
引用對象的初始狀態,表示GC要按照特殊的邏輯來處理這個對象,大體方法就是按照上一節提到的。
Pending
若是一個引用對象,其註冊了隊列,在入隊以前,會進入這個狀態。
Enqueued
一個引用對象入隊後,進入這個狀態。
Inactive
一個引用對象出隊後,或者沒有註冊隊列,其隊列是一個特殊的對象java.lang.ref.ReferenceQueue.NULL
,表示這個對象已經沒有用了。
平常開發工做中,用到除強引用以外的引用的可能性很小,只有在處理一些性能敏感的邏輯時,才須要考慮使用這些特殊的引用,下面就舉幾個相關的實際例子,分析其使用場景。
弱引用的使用比較簡單,如Guava中的LocalCache中就是用了SoftReference來作緩存。
弱引用是使用的比較多的,從上文的描述可知:對於一個「目標對象A」,若是還有強引用指向它,那麼從一個弱引用就能夠訪問到A,一旦沒有強引用指向它,那麼就能夠認爲,從這個弱引用就訪問不到A了(實際狀況可能會有誤差)。
根據這個特色,JDK中註釋說到,弱引用一般用來作映射表( canonicalizing mapping),總結下來映射表有這樣2個特色:
若是表中的Key(或者Value)還存在強引用,則能夠經過Key訪問到Value,反之則訪問不到
換句話說,只要有原始的Key,就能訪問到Value。
映射表自己不會影響其中Key或者Value的GC
在JDK中有不少個地方使用了它的這個特色,下面是2個具備表明性的實例。
ThreadLocal的原理比較簡單,線程中保持了一個以ThreadLocal
爲Key的ThreadLocal.ThreadLocalMap
對象threadLocals
,其中的Entry如代碼1中所示:
//代碼1 static class Entry extends WeakReference> { /** The value associated with this ThreadLocal. */ Object value; //其保持了對做爲Key的ThreadLocal對象的弱引用 Entry(ThreadLocal k, Object v) { super(k); value = v; } } 複製代碼
其引用關係以下圖所示:
從上圖能夠看出,當引用2被清除以後(ThreadLocal對象再也不使用),若是引用4爲強引用,則不論引用1是否還存在,只要Thread對象還沒死,則對象1和對象2永遠不會被釋放。
動態代理是Java世界一個十分重要的特性,對於須要作AOP的業務邏輯十分重要。JDK自己提供了基於反射的動態代理機制,其原理大體是要經過預先定義的接口(interface)來動態的生成代理類,並將之代理到InvocationHandler
的實例上去。JDK的動態代理使用起來很簡單,以下代碼2中所示:
//代碼2
package me.lk;
import java.lang.reflect.*;
public class TestProxy {
/**
* 兩個預約義的須要被代理的接口
*/
public static interface ProxiedInterface {
void proxiedMethod();
}
public static interface ProxiedInterface2 {
void proxiedMethod2();
}
/**
* 真正的處理邏輯
*/
public static class InvoHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("in proxy:" + method.getName());
//其餘邏輯
System.out.println("in proxy end");
return null;
}
}
public static void main(String[] args) {
InvoHandler ih = new InvoHandler();
ProxiedInterface proxy = (ProxiedInterface) Proxy.newProxyInstance(TestProxy.class.getClassLoader(), new Class[]{ProxiedInterface.class, ProxiedInterface2.class}, ih);
proxy.proxiedMethod();
ProxiedInterface2 p = (ProxiedInterface2) proxy;
p.proxiedMethod2();
}
}複製代碼
其實現原理其實也很簡單,就是在方法Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
中動態生成一個「實現了interfaces
中全部接口」並「繼承於Proxy」的代理類,並生成相應的對象。
//代碼3
public static Object newProxyInstance(ClassLoader loader,
Class
[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class
[] intfs = interfaces.clone();
//驗證真實調用者的權限
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
//查詢或生成代理類
Class
cl = getProxyClass0(loader, intfs);
//驗證調用者對代理類的權限,並生成對象
。。。省略代碼
}
private static Class
getProxyClass0(ClassLoader loader,
Class
... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// 經過緩存獲取代理類
return proxyClassCache.get(loader, interfaces);
}複製代碼
生成動態類的邏輯在方法java.lang.reflect.Proxy.ProxyClassFactory.apply(ClassLoader, Class<?>[])
,代碼以下:
//代碼4 @Override public Class apply(ClassLoader loader, Class [] interfaces) { Map, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length); //驗證接口,驗證接口是否重複,驗證loader對接口的可見性 //生成包名和修飾符 //生成類 byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); try { return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { /* * 生成失敗 */ throw new IllegalArgumentException(e.toString()); } } 複製代碼
爲了更高效的使用動態代理,Proxy類中採用了緩存策略(代碼3中的proxyClassCache
)來緩存動態生成的代理類,因爲這個緩存對象是靜態的,也就是說一旦Proxy類被加載,proxyClassCache
極可能永遠不會被GC回收,然而它必需要保持對其中的ClassLoader和Class的引用,若是這裏使用強引用,則它們也隨着proxyClassCache
永遠不會被GC回收。
再也不使用的類和類加載器若是沒法被GC,其內存泄漏的風險很大。因此WeakCache中設計爲,「傳入的類加載器」和「生成的代理類」爲弱引用。
類和類加載器是相互引用的,而類加載器的內存泄漏可能會帶來很嚴重的問題,有興趣能夠去看這篇文章:Reloading Java Classes 201: How do ClassLoader leaks happen?
//代碼5 /** * a cache of proxy classes */ //ClassLoader 用來加載預約義接口(interface)和生成代理類的類加載器 //Class [] 預約義接口(interface) //Class 生成的代理類 private static final WeakCache[], Class > proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory()); /** * CacheKey containing a weakly referenced {@code key}. It registers * itself with the {@code refQueue} so that it can be used to expunge * the entry when the {@link WeakReference} is cleared. */ private static final class CacheKey 複製代碼extends WeakReference /** * A {@link Value} that weakly references the referent. */ private static final class CacheValue extends WeakReference implements Value
從代碼5中能夠看出,WeakCache對象中保持了對ClassLoader(包裝爲CacheKey
)和代理類(包裝爲CacheValue
)的弱引用,因此當此類加載器和代理類再也不被強引用時,它們就會被回收。
然而,WeakCache的實現是有問題的,在java.lang.reflect.WeakCache.reverseMap
和java.lang.reflect.WeakCache.valueFactory
中的狀態在極限狀況下可能會出現不一樣步,致使一個代理類被調用java.lang.reflect.Proxy.isProxyClass(Class<?>)
的返回值不正確。具體能夠參考Race Condition in java.lang.reflect.WeakCache。
不過這個問題在JDK9中已經不存在了。
在上一節,並無列出虛引用的使用場景,由於它的使用場景十分單一。PhantomReference設計的目的就是能夠在對象被回收以前收到通知(經過註冊的隊列),因此它沒有不含註冊隊列的構造器(只有public PhantomReference(T referent, ReferenceQueue<? super T> q)
,但你仍能夠傳null
進去),但這種場景在JDK裏並無出現,也不多有開發者使用它。
從PhantomReference類的源代碼可知,你永遠沒法經過它獲取到它引用的那個對象(其get()
方法永遠返回null
),可是它又能夠阻止其引用的目標對象被GC回收。從上文可知,一般一個不可達(強不可達、軟不可達、弱不可達)的對象會被finalize,而後被回收。但若是它在被回收前,GC發現它仍然是虛可達,那麼它就不會回收這塊內存,而這塊內存又不能被訪問到,那麼這塊內存就泄漏了。
想要虛引用的「目標對象」被回收,必須讓「引用對象」自己不可達,或者顯式地清除虛引用。因此若是使用不當,極可能會形成內存泄漏,這也是它使用範圍不廣的緣由之一。
代碼6演示了這3種引用分別的GC行爲:
//代碼6 private static List2017-07-03T12:36:22.995+0800: [Full GC (System.gc()) [PSYoungGen: 40971K->40960K(76288K)] [ParOldGen: 492061K->492061K(506880K)] 533033K->533022K(583168K), [Metaspace: 2727K->2727K(1056768K)], 0.0610620 secs] [Times: user=0.23 sys=0.00, real=0.06 secs] 2017-07-03T12:36:24.391+0800: [Full GC (System.gc()) [PSYoungGen: 40960K->40960K(76288K)] [ParOldGen: 1065502K->1065502K(1087488K)] 1106462K->1106462K(1163776K), [Metaspace: 2017-07-03T12:36:32.291+0800: [Full GC (System.gc()) [PSYoungGen: 40962K->40962K(76288K)] [ParOldGen: 2581022K->2581022K(2621952K)] 2621985K->2621985K(2698240K), [Metaspace: 2727K->2727K(1056768K)], 0.3106258 secs] [Times: user=2.31 sys=0.00, real=0.31 secs] 2017-07-03T12:36:32.610+0800: [GC (System.gc()) [PSYoungGen: 40962K->128K(76288K)] 2662945K->2663070K(2739712K), 0.6298054 secs] [Times: user=4.63 sys=0.00, real=0.63 secs] 2017-07-03T12:36:33.240+0800: [Full GC (System.gc()) [PSYoungGen: 128K->0K(76288K)] [ParOldGen: 2662942K->2662945K(2663424K)] 2663070K->2662945K(2739712K), [Metaspace: 2727K->2727K(1056768K)], 0.2898513 secs] [Times: user=2.25 sys=0.00, real=0.29 secs] 2017-07-03T12:36:34.096+0800: [Full GC (System.gc()) [PSYoungGen: 40960K->40960K(76288K)] [ParOldGen: 2744865K->2744865K(2746368K)] 2785825K->2785825K(2822656K), [Metaspace: 2727K->2727K(1056768K)], 0.3282086 secs] [Times: user=2.47 sys=0.00, real=0.33 secs] 2017-07-03T12:36:34.425+0800: [Full GC (Ergonomics) [PSYoungGen: 40960K->40960K(76288K)] [ParOldGen: 2744865K->2744865K(2777088K)] 2785825K->2785825K(2853376K), [Metaspace: 2727K->2727K(1056768K)], 0.3061587 secs] [Times: user=2.32 sys=0.00, real=0.31 secs] 2017-07-03T12:36:34.731+0800: [Full GC (Allocation Failure) [PSYoungGen: 40960K->0K(76288K)] [ParOldGen: 2744865K->531K(225280K)] 2785825K->531K(301568K), [Metaspace: 2727K->2727K(1056768K)], 0.1559132 secs] [Times: user=0.02 sys=0.14, real=0.16 secs] 2017-07-03T12:36:34.890+0800: [GC (System.gc()) [PSYoungGen: 40960K->32K(76288K)] 41491K->82483K(301568K), 0.0304114 secs] [Times: user=0.14 sys=0.00, real=0.03 secs] 2017-07-03T12:36:34.920+0800: [Full GC (System.gc()) [PSYoungGen: 32K->0K(76288K)] [ParOldGen: 82451K->41491K(225280K)] 82483K->41491K(301568K), [Metaspace: 2727K->2727K(1056768K)], 0.0179676 secs] [Times: user=0.05 sys=0.00, real=0.02 secs] 2017-07-03T12:36:34.941+0800: [GC (System.gc()) [PSYoungGen: 41649K->32K(76288K)] 83140K->123443K(301568K), 0.0323917 secs] [Times: user=0.11 sys=0.00, real=0.03 secs] 2017-07-03T12:36:34.973+0800: [Full GC (System.gc()) [PSYoungGen: 32K->0K(76288K)] [ParOldGen: 123411K->82451K(225280K)] 123443K->82451K(301568K), [Metaspace: 2727K->2727K(1056768K)], 0.0424672 secs] [Times: user=0.20 sys=0.00, real=0.04 secs] 2017-07-03T12:36:35.414+0800: [Full GC (System.gc()) [PSYoungGen: 41011K->40960K(76288K)] [ParOldGen: 287252K->287252K(308224K)] 328264K->328212K(384512K), [Metaspace: 2727K->2727K(1056768K)], 0.0520262 secs] [Times: user=0.33 sys=0.00, real=0.05 secs] 2017-07-03T12:36:48.569+0800: [Full GC (Ergonomics) [PSYoungGen: 40960K->40960K(76288K)] [ParOldGen: 2744854K->2744854K(2777088K)] 2785815K->2785815K(2853376K), [Metaspace: 2727K->2727K(1056768K)], 0.3476025 secs] [Times: user=2.45 sys=0.02, real=0.35 secs] 2017-07-03T12:36:48.916+0800: [Full GC (Allocation Failure) [PSYoungGen: 40960K->0K(76288K)] [ParOldGen: 2744854K->534K(444928K)] 2785815K->534K(521216K), [Metaspace: 2727K->2727K(1056768K)], 0.1644360 secs] [Times: user=0.02 sys=0.16, real=0.17 secs] 2017-07-03T12:36:49.084+0800: [GC (System.gc()) [PSYoungGen: 40960K->32K(76288K)] 41494K->82486K(521216K), 0.0444057 secs] [Times: user=0.22 sys=0.00, real=0.04 secs] 2017-07-03T12:36:49.128+0800: [Full GC (System.gc()) [PSYoungGen: 32K->0K(76288K)] [ParOldGen: 82454K->41494K(444928K)] 82486K->41494K(521216K), [Metaspace: 2727K->2727K(1056768K)], 0.0288512 secs] [Times: user=0.11 sys=0.00, real=0.03 secs] 複製代碼2017-07-03T12:32:55.214+0800: [GC (System.gc()) [PSYoungGen: 43581K->728K(76288K)] 43581K->41696K(251392K), 0.0354037 secs] [Times: user=0.20 sys=0.00, real=0.04 secs] 2017-07-03T12:32:55.252+0800: [Full GC (System.gc()) [PSYoungGen: 728K->0K(76288K)] [ParOldGen: 40968K->41502K(175104K)] 41696K->41502K(251392K), [Metaspace: 2726K->2726K(1056768K)], 0.0258447 secs] [Times: user=0.08 sys=0.00, real=0.03 secs] 2017-07-03T12:32:55.533+0800: [Full GC (System.gc()) [PSYoungGen: 41309K->40960K(76288K)] [ParOldGen: 164381K->164381K(175104K)] 205690K->205341K(251392K), [Metaspace: 2726K->2726K(1056768K)], 0.0389489 secs] [Times: user=0.25 sys=0.00, real=0.04 secs] 2017-07-03T12:32:57.413+0800: [Full GC (System.gc()) [PSYoungGen: 40960K->40960K(76288K)] [ParOldGen: 1024541K->1024541K(1046016K)] 1065502K->1065502K(1122304K), [Metaspace: 2726K->2726K(1056768K)], 0.1263574 secs] [Times: user=0.94 sys=0.00, real=0.13 secs] 2017-07-03T12:33:05.364+0800: [Full GC (System.gc()) [PSYoungGen: 40962K->40962K(76288K)] [ParOldGen: 2581022K->2581022K(2621952K)] 2621984K->2621984K(2698240K), [Metaspace: 2726K->2726K(1056768K)], 0.2474419 secs] [Times: user=1.69 sys=0.00, real=0.25 secs] 2017-07-03T12:33:07.447+0800: [Full GC (Ergonomics) [PSYoungGen: 40960K->40960K(76288K)] [ParOldGen: 2744864K->2744864K(2777088K)] 2785824K->2785824K(2853376K), [Metaspace: 2726K->2726K(1056768K)], 0.2825105 secs] [Times: user=1.79 sys=0.00, real=0.28 secs] 2017-07-03T12:33:07.729+0800: [Full GC (Allocation Failure) [PSYoungGen: 40960K->40960K(76288K)] [ParOldGen: 2744864K->2744851K(2777088K)] 2785824K->2785812K(2853376K), [Metaspace: 2726K->2726K(1056768K)], 0.8902204 secs]Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at me.lk.TestReference.testPhantomRefLeakOOM(TestReference.java:109) at me.lk.TestReference.main(TestReference.java:50) [Times: user=3.79 sys=0.00, real=0.89 secs] Heap PSYoungGen total 76288K, used 43025K [0x000000076b400000, 0x0000000770900000, 0x00000007c0000000) eden space 65536K, 65% used [0x000000076b400000,0x000000076de04408,0x000000076f400000) from space 10752K, 0% used [0x000000076f400000,0x000000076f400000,0x000000076fe80000) to space 10752K, 0% used [0x000000076fe80000,0x000000076fe80000,0x0000000770900000) ParOldGen total 2777088K, used 2744851K [0x00000006c1c00000, 0x000000076b400000, 0x000000076b400000) object space 2777088K, 98% used [0x00000006c1c00000,0x0000000769484fb8,0x000000076b400000) Metaspace used 2757K, capacity 4490K, committed 4864K, reserved 1056768K class space used 310K, capacity 386K, committed 512K, reserved 1048576K複製代碼2017-07-03T12:32:55.214+0800: [GC (System.gc()) [PSYoungGen: 43581K->728K(76288K)] 43581K->41696K(251392K), 0.0354037 secs] [Times: user=0.20 sys=0.00, real=0.04 secs] 2017-07-03T12:32:55.252+0800: [Full GC (System.gc()) [PSYoungGen: 728K->0K(76288K)] [ParOldGen: 40968K->41502K(175104K)] 41696K->41502K(251392K), [Metaspace: 2726K->2726K(1056768K)], 0.0258447 secs] [Times: user=0.08 sys=0.00, real=0.03 secs] 2017-07-03T12:32:55.533+0800: [Full GC (System.gc()) [PSYoungGen: 41309K->40960K(76288K)] [ParOldGen: 164381K->164381K(175104K)] 205690K->205341K(251392K), [Metaspace: 2726K->2726K(1056768K)], 0.0389489 secs] [Times: user=0.25 sys=0.00, real=0.04 secs] 2017-07-03T12:32:57.413+0800: [Full GC (System.gc()) [PSYoungGen: 40960K->40960K(76288K)] [ParOldGen: 1024541K->1024541K(1046016K)] 1065502K->1065502K(1122304K), [Metaspace: 2726K->2726K(1056768K)], 0.1263574 secs] [Times: user=0.94 sys=0.00, real=0.13 secs] 2017-07-03T12:33:05.364+0800: [Full GC (System.gc()) [PSYoungGen: 40962K->40962K(76288K)] [ParOldGen: 2581022K->2581022K(2621952K)] 2621984K->2621984K(2698240K), [Metaspace: 2726K->2726K(1056768K)], 0.2474419 secs] [Times: user=1.69 sys=0.00, real=0.25 secs] 2017-07-03T12:33:07.447+0800: [Full GC (Ergonomics) [PSYoungGen: 40960K->40960K(76288K)] [ParOldGen: 2744864K->2744864K(2777088K)] 2785824K->2785824K(2853376K), [Metaspace: 2726K->2726K(1056768K)], 0.2825105 secs] [Times: user=1.79 sys=0.00, real=0.28 secs] 2017-07-03T12:33:07.729+0800: [Full GC (Allocation Failure) [PSYoungGen: 40960K->40960K(76288K)] [ParOldGen: 2744864K->2744851K(2777088K)] 2785824K->2785812K(2853376K), [Metaspace: 2726K->2726K(1056768K)], 0.8902204 secs]Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at me.lk.TestReference.testPhantomRefLeakOOM(TestReference.java:109) at me.lk.TestReference.main(TestReference.java:50) [Times: user=3.79 sys=0.00, real=0.89 secs] Heap PSYoungGen total 76288K, used 43025K [0x000000076b400000, 0x0000000770900000, 0x00000007c0000000) eden space 65536K, 65% used [0x000000076b400000,0x000000076de04408,0x000000076f400000) from space 10752K, 0% used [0x000000076f400000,0x000000076f400000,0x000000076fe80000) to space 10752K, 0% used [0x000000076fe80000,0x000000076fe80000,0x0000000770900000) ParOldGen total 2777088K, used 2744851K [0x00000006c1c00000, 0x000000076b400000, 0x000000076b400000) object space 2777088K, 98% used [0x00000006c1c00000,0x0000000769484fb8,0x000000076b400000) Metaspace used 2757K, capacity 4490K, committed 4864K, reserved 1056768K class space used 310K, capacity 386K, committed 512K, reserved 1048576K複製代碼2017-07-03T12:45:14.774+0800: [GC (System.gc()) [PSYoungGen: 43581K->696K(76288K)] 43581K->41664K(251392K), 0.0458469 secs] [Times: user=0.17 sys=0.00, real=0.05 secs] 2017-07-03T12:45:14.820+0800: [Full GC (System.gc()) [PSYoungGen: 696K->0K(76288K)] [ParOldGen: 40968K->41502K(175104K)] 41664K->41502K(251392K), [Metaspace: 2726K->2726K(1056768K)], 0.0198788 secs] [Times: user=0.08 sys=0.00, real=0.02 secs] 2017-07-03T12:45:14.842+0800: [GC (System.gc()) [PSYoungGen: 42231K->32K(76288K)] 83734K->82495K(251392K), 0.0367363 secs] [Times: user=0.22 sys=0.00, real=0.04 secs] 2017-07-03T12:45:14.879+0800: [Full GC (System.gc()) [PSYoungGen: 32K->0K(76288K)] [ParOldGen: 82463K->41501K(175104K)] 82495K->41501K(251392K), [Metaspace: 2727K->2727K(1056768K)], 0.0198085 secs] [Times: user=0.08 sys=0.00, real=0.02 secs] 2017-07-03T12:45:14.901+0800: [GC (System.gc()) [PSYoungGen: 41786K->32K(76288K)] 83287K->82493K(251392K), 0.0327529 secs] [Times: user=0.19 sys=0.00, real=0.03 secs] 2017-07-03T12:45:14.934+0800: [Full GC (System.gc()) [PSYoungGen: 32K->0K(76288K)] [ParOldGen: 82461K->41501K(175104K)] 82493K->41501K(251392K), [Metaspace: 2727K->2727K(1056768K)], 0.0283782 secs] [Times: user=0.17 sys=0.00, real=0.03 secs] 2017-07-03T12:45:14.964+0800: [GC (System.gc()) [PSYoungGen: 41497K->32K(76288K)] 82998K->82493K(251392K), 0.0336216 secs] [Times: user=0.20 sys=0.00, real=0.03 secs] 2017-07-03T12:45:14.998+0800: [Full GC (System.gc()) [PSYoungGen: 32K->0K(76288K)] [ParOldGen: 82461K->41501K(175104K)] 82493K->41501K(251392K), [Metaspace: 2727K->2727K(1056768K)], 0.0211702 secs] [Times: user=0.13 sys=0.00, real=0.02 secs] 2017-07-03T12:45:15.021+0800: [GC (System.gc()) [PSYoungGen: 41309K->32K(76288K)] 82810K->82493K(251392K), 0.0445368 secs] [Times: user=0.30 sys=0.00, real=0.05 secs] 2017-07-03T12:45:15.066+0800: [Full GC (System.gc()) [PSYoungGen: 32K->0K(76288K)] [ParOldGen: 82461K->41501K(175104K)] 82493K->41501K(251392K), [Metaspace: 2727K->2727K(1056768K)], 0.0219968 secs] [Times: user=0.11 sys=0.00, real=0.02 secs] 2017-07-03T12:45:15.090+0800: [GC (System.gc()) [PSYoungGen: 41186K->32K(76288K)] 82688K->82493K(251392K), 0.0436528 secs] [Times: user=0.36 sys=0.00, real=0.04 secs] 2017-07-03T12:45:15.133+0800: [Full GC (System.gc()) [PSYoungGen: 32K->0K(76288K)] [ParOldGen: 82461K->41501K(175104K)] 82493K->41501K(251392K), [Metaspace: 2727K->2727K(1056768K)], 0.0219814 secs] [Times: user=0.11 sys=0.00, real=0.02 secs]複製代碼