黑马程序员_关于虚拟机内存的知识点补充

来源:互联网 发布:阿尔法宝贝复制软件 编辑:程序博客网 时间:2024/06/04 17:49

------- android培训java培训、期待与您交流! ----------

以下内容是我学习《疯狂JAVA程序员的基础修养》的阅读笔记

关于内存回收的知识点的补充

1、JAVA内存的管理,包括内存分配(创建JAVA对象)和内存回收(回收JAVA对象)。

 

2、可以把JVM内存中的对象引用理解成一种有向图,把引用变量、对象都当成有向图的顶点,将引用关系当成图的有向边,有向边总是从引用端指向被引用的JAVA对象。因为JAVA所有的对象都由一条条线程创建进来的,因此可以把线程对象当成有向图的起始顶点。

 

3、JVM的垃圾回收机制采用有向图的方式来管理内存中的对象,因此可以方便地解决循环引用的问题。

 

4、堆中内存根据有向图状态,可分为如下3个状态:

1)可达状态:存在引用

2)可恢复状态:不存在引用,但未执行finallize()方法

3)不可达状态:不存在引用,不存在finallize()方法或已执行过finallize()方法后,仍然无法被引用。

 

5、四种引用

1)强引用

程序创建一个对象,并把这个对象赋给一个引用变量,这个引用变量就是强引用。垃圾回收,不会回收强引用。强引用也是造成JAVA内存泄露的主要原因。

2)软引用(SoftReference

软引用需要通过SoftReference来实现,当一个对象只具有软引用时,它有可能被垃圾回收机制收回。对于只有软引用的对象而言,当系统内存空间足够时,它不会被系统回收,程序也可使用该对象;当系统内存空间不足时,系统将会回收它。

public static void main(String[] args) {//定义一个软引用数组(可以非常大)SoftReference[] people = new SoftReference[100000];//初始化软引用for(int i=0; i<people.length; i++) {//新建引用people[i] = new SoftReference(new Object());}System.out.println(people[1].get());System.out.println(people[2].get());//通知系统回收System.gc();System.runFinalization();//重新查看引用对象System.out.println(people[1].get());System.out.println(people[2].get());}

注:这边代码验证,要调整虚拟机运行内存(往小调)


3)弱引用

弱引用与软引用有点类似,区别在于弱引用生存周期更短。在下一次垃圾回收前,存在。在下一次垃圾回收后,清除。

public static void main(String[] args) throws InterruptedException {//定义并初始化弱引用WeakReference wr = new WeakReference(new Object());//查看引用对象System.out.println(wr);//通知系统回收System.gc();//重新查看引用对象System.out.println(wr.get());}


当程序有大量的JAVA对象需要使用弱引用时,可以考虑使用WeakHashMap来保存它们。

在垃圾回收机制运行前,WeakHashMap的功能与普通的HashMap并没有太大的区别,它们的功能完全相似,但一旦垃圾回收机制被执行,WeakHashMap中的所有键值对都会被清空,除了某些保持强引用的key

4)虚引用

虚引用的主要作用就是跟踪对象被垃圾回收的状态。

 

6、用途说明

如果希望尽可能减少程序运行在其生命周期中所占内存的大小,可以使用这些引用类。

注意:如果使用这些特殊引用类,请不要对对象,保留其它的强引用。


7JAVA内存泄漏的形式:

如果程序中有一些Java对象,它们处于可达状态,但程序以后永远都不再访问它们,那么它们所占的内存空间也不会被回收,它们所占用的空间也会产生内存泄漏。

例如:以ArrayListremove()方法为参考,方法中,会将List尾部的的对象显式的置null

那是因为ArrayList底层的本质是一个数组。(数组长度是不可变的)所以即使,计数器的长度小于数组的长度,那数组中对对象的引用,依然存在这应该就是传说中的内存泄漏。

 

8、垃圾回收机制

垃圾回收机制主要完成以下两件事:

1)跟踪并监控每个JAVA对象,当某个对象处于不扩大状态时,回收该对象所占内存。

2)清理内存分配、回收过程中产生的内存碎片。

 

9、垃圾回收的基本设计算法(这边仅做了了解)

1)串行回收(Serial)和并行回收(Parallel

并行回收的执行效率很到,但复杂度增加。

2)并发执行(Concurrent)和应用程序停止(Stop-the-world

3)压缩(Compacting/不压缩(Non-compacting)和复制(Copying

以上具体分析:

复制(常用于Young代)

标记清除(常用于Old代)

标记压缩

 

10、分代

Young(新生代)

Old(老年代)

Permanent(永生代)

1)规律

绝大多数的对象不会被长时间引用,这些对象在其Young期间就会被回收。

很老的对象和很新的对象之前很少存在相互引用

 

2)Young

Young代采用复制算法只需要遍历那些处于可达状态的对象,而且这些对象的数量较少,可复制成本也不大,因此可以充分发挥复制算法的优点。

Young代由一个Eden区和两个Suvivor区构成。

3)Old

如果Young代中的对象经过数次垃圾回收依然没有被回收掉,即这个对象经过足够长的时间还处于可达状态,垃圾回收机制就会将这个对象转移到Old代。

Old代垃圾回收具有如下两个特征:

a.Old代的回收频率无须太高,因为很少有对象会死掉。

b.每次Old代执行垃圾回收都需要更长的时间来完成。

垃圾回收通常会使用标记压缩算法。

4)Permanent

Permanent代主要用于装在Class、方法信息,默认为64MB,垃圾回收机制通常不会回收Permanent代中的对象。对于那些需要加载很多类的服务器程序,往往需要加大Permanent代的内存,否则可能会因为内存不足而导致程序终止。

 

11、主要回收和次要回收

主要回收:对Young代和Old代进行回收。

次要回收:只对Young代进行回收。

 

12、常见的垃圾回收器(了解吧)

1)串行回收器

Young代采用串行复制算法(单线程),Old代采用标记压缩算法(单线程)。

2)并行回收器

相对于串行回收器,只是在Young代回收中,引入了多线程实现。

3)并行压缩回收器(JDK1.5u6以后引入)

相对于并行回收器,其Old代采用分阶段操作。

mark阶段:标记对象

summary阶段:判定回收区

compact阶段:复制对象

4)并发标识-清理回收器

 

13、内存管理的一些小技巧

1)尽量使用直接量

例如:

String str = “hello”;

而不是:

String str = new String(“hello”);

2)使用StringBuilderStringBuffer进行字符串连接

3)尽早释放无用对象的引用

在调用耗时、耗内存的操作前,尽量将无用对象的引用置null

4)尽量少用静态变量

因为静态变量在永生代,其引用的对象,也会被长期持有。

5)避免在经常调用的方法、循环中创建Java对象

6)缓存经常使用的对象

方案:

使用HashMap进行缓存

直接使用某些开源的缓存项目

7)尽量不要使用finallize方法

8)考虑使用SoftReference


------- android培训java培训、期待与您交流! ----------

0 0