1.为什么JVM要分代?
  • 有些对象生活周期短。如下代码和图示:
  1. public class MemoryAol {
  2. public static void main(String[] args) throws InterruptedException {
  3. while (true) {
  4. loadUsers();
  5. Thread.sleep(1000);
  6. }
  7. }
  8. private static void loadUsers() {
  9. UserUtil userUtil = new UserUtil();
  10. userUtil.loadUsers();
  11. }
  12. }

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

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

2-2.JVM的分代模型及对象流动 - 图2
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 | 每个线程栈的内存大小 |

画个图更加具体一些,如下图:
2-2.JVM的分代模型及对象流动 - 图3


_