2.JVM的分代模型及对象流动

JVM系列

1.JVM运行机制的整体脉络
2.JVM的分代模型及对象流动
3.常见的垃圾回收器及算法
4.ParNew和CMS的工作原理

1.为什么JVM要分代?
  • 有些对象生活周期短。如下代码和图示:
public class MemoryAol {

    public static void main(String[] args) throws InterruptedException {
        while (true) {
            loadUsers();
            Thread.sleep(1000);
        }
    }
    
    private static void loadUsers() {
        UserUtil userUtil = new UserUtil();
        userUtil.loadUsers();
    }
}
1-8.png

如上所示的代码,main方法一直在运行,UserUtil对象会一直创建,但是当loadUsers执行完毕会进行出栈,此时年轻代堆里的刚创建的对象就没人引用了,这种对象当内存不足时是要被回收的,所以他们的存活周期很短。

  • 有些对象要长期在内存里。 如下代码和图示。
public class MemoryAol {
    private static UserUtil userUtil = new UserUtil();
    public static void main(String[] args) throws InterruptedException {
        while (true) {
            loadUsers();
            Thread.sleep(1000);
        }
    }

    private static void loadUsers() {
        userUtil.loadUsers();
    }
}
1-9.png

如上代码,同样的,main方法一直在运行,不断地执行loadUsers,然后loadUsers又使用到userUtil,但这次不是局部变量,而是类的静态变量,引在存放在方法区,所以即使loadUsers方法不断地进栈出栈也不会对userUtil进行回收。随着程序不断运行,当它达到一定条件就会晋升到老年代,这时候这种对象成为了长期存活的对象了。

2.JVM是如何分代的?

JVM主要有如下三个分代:

  • 年轻代
    年轻代对象主要的特点是存活周期短,回收频率高,回收速度快,年轻代还分为Eden区,Survivor1区,Survivor2区,三者默认比例8:1:1。
  • 年老代
    年老代对象主要特点是存活周期长,回收频率低,回收速度慢,尽量减少老年代回收的频率及次数。
  • 永久代
    存放一些类信息及常量,当内存不足时同样也会进行回收,回收条件看下面。
3.什么时候触发新生代垃圾回收,永久代什么情况下会被回收?
  • 新生代的回收时机
    当新生代Eden区快满的时候(不足以存放新建对象)会触发新生代回收(minor GC),会有短暂的Stop the world。后续文章会详细说明回收机制,采用什么算法及垃圾回收器,以及优缺点等。
  • 永久代回收时机
    当进行Full GC的时候,同时会检查并回收永久代内存。永久代内存回收需满足以下全部条件:
    1.该类的所有实例对象已经从JAVA堆内存里被回收。
    2.加载这个类的ClassLoader已经被回收了。
    3.该类的Class对象没有任何引用,比如User.class没有被引用。
4.对象在JVM是怎么分配和流动的?
  • 新建对象放哪
    新建对象放在年轻代的Eden区
  • 大对象怎么办
    大对象直接晋升老年代,通过-XX:PretenureSizeThreshold=<大小>,当大于设定大小的时候直接在老年代创建。
  • 什么时候从年轻代升到老年代
    每次发生minor gc,存活对象年龄加1,当年经代的对象年龄达到设置的大小,参数-XX:MaxTenuringThreshold设置,就会晋升到老年代。
5.JVM的参数设置
参数 例子 描述
-Xms -Xms2048m java堆内存大小
-Xmx -Xmx2048m java最大堆内存大小,一般情况下和上面的设置一样
-Xmn -Xmn1024m 年轻代内存大小,扣除年轻代剩下的堆内存就是年老代的
-XX:PermSize -XX:PermSize=256m 永久代(方法区)内存大小
-XX:MaxPermSize -XX:MaxPermSize=256m 永久代最大内存大小
-Xss -Xss1m 每个线程栈的内存大小

画个图更加具体一些,如下图:

1-7.jpg

你可能感兴趣的:(2.JVM的分代模型及对象流动)