专栏名称: 刘望舒
腾讯云最具价值专家
目录
相关文章推荐
鸿洋  ·  务必立即拿下软考证(政策红利) ·  20 小时前  
复利大王  ·  00后新观念!与男朋友保持非婚姻长期关系 ·  21 小时前  
郭霖  ·  Android ... ·  3 天前  
复利大王  ·  头等舱的空姐 ·  昨天  
复利大王  ·  王石最新朋友圈 ·  昨天  
51好读  ›  专栏  ›  刘望舒

Java四种引用解析以及在Android的应用

刘望舒  · 掘金  · android  · 2018-01-13 07:32

正文

请到「今天看啥」查看全文


● 当发生GC的时候打印GC的简单信息,当程序运行结束打印GC详情

●. 强引用

代码中普遍存在的类似"Object obj = new Object()"这类的引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象,哪怕是JVM抛出OutOfMemoryError异常,也不会回收内存的,下面看一段代码即可明白

public class GCDemo {    private static final int _1MB = 1024 * 1024;    private byte[] bytes = new byte[_1MB];    public static void main(String[] args) {        test();    }    private static void test() {        byte[] bytes1 = new byte[5 * _1MB];        byte[] bytes2 = new byte[5 * _1MB];        System.gc();    }}结果如下:  [Full GC (System.gc()) [Tenured: 5120K->5120K(10240K), 0.0018258 secs] 10993K->10843K(19456K), [Metaspace: 3090K->3090K(1056768K)], 0.0018492 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] Heap par new generation   total 9216K, used 6023K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)  eden space 8192K,  73% used [0x00000000fec00000, 0x00000000ff1e1db0, 0x00000000ff400000)  from space 1024K,   0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)  to   space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000) tenured generation   total 10240K, used 5120K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)   the space 10240K,  50% used [0x00000000ff600000, 0x00000000ffb00010, 0x00000000ffb00200, 0x0000000100000000) Metaspace       used 3110K, capacity 4494K, committed 4864K, reserved 1056768K  class space    used 340K, capacity 386K, committed 512K, reserved 1048576K

我们可以看到,即使GC了也没有回收,而且共有10993K内存转移到了老年代了,从10993K->10843K可以判断出并没有回收掉,也就是说 10M的字节没有被回收 ,那么我们加大一点测试看看会不会内存错误,

public class GCDemo {    private static final int _1MB = 1024 * 1024;    private byte[] bytes = new byte[_1MB];    public static void main(String[] args) {        test();    }    private static void test() {        byte[] bytes1 = new byte[5 * _1MB];        byte[] bytes2 = new byte[10* _1MB];        System.gc();    }}可以看到发生错误了,[Full GC (Allocation Failure) [TenuredException in thread "main" java.lang.OutOfMemoryError: Java heap space    at Collections.GCDemo.test(GCDemo.java:17)    at Collections.GCDemo.main(GCDemo.java:12)    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)    at java.lang.reflect.Method.invoke(Method.java:498)    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)Java HotSpot(TM) 64-Bit Server VM warning: Using the ParNew young collector with the Serial old collector is deprecated and will likely be removed in a future release: 5725K->5700K(10240K), 0.0018018 secs] 5725K->5700K(19456K), [Metaspace: 3042K->3042K(1056768K)], 0.0018229 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] Heap par new generation   total 9216K, used 322K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)

那要怎样释放呢,手动置为null,就失去了GC Roots引用连,这样就可以回收了

public class GCDemo {    private static final int _1MB = 1024 * 1024;    private byte[] bytes = new byte[_1MB];    public static void main(String[] args) {        test();        //System.gc    }    private static void test() {        byte[] bytes1 = new byte[5 * _1MB];        byte[] bytes2 = new byte[5 * _1MB];        bytes1 = null;        bytes2 = null;        System.gc();    }}[Full GC (System.gc()) [TenuredJava HotSpot(TM) 64-Bit Server VM warning: Using the ParNew young collector with the Serial old collector is deprecated and will likely be removed in a future release: 5120K->602K(10240K), 0.0018229 secs] 11015K->602K(19456K), [Metaspace: 3069K->3069K(1056768K)], 0.0018489 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] Heap par new generation   total 9216K, used 299K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)

可以看到从11015K->602K,说明手动置null之后经过了一个gc,那些都被回收了,实际上如果不手动置为null,也可以在方法执行之后再调用System.gc()方法的,这样一样可以回收内存,其原因是test()只是一个方法,当JVM执行完方法返回的时候,会清空当前的栈帧,而测试的是在方法内分配的,自然就会随着方法结束而释放掉内存了,就是注释去掉,然后不用手动置null,是一样的效果来的。







请到「今天看啥」查看全文