java的内存划分
  1. java堆:又名Heap区,包含young/old两大板块。young区又分为Eden和Survivor区(共2个,分别是From和To,也称S0,S1),比例是8:1。
    -Xms 堆内存的最小大小,默认为物理内存的1/64
    -Xmx 堆内存的最大大小,默认为物理内存的1/4
    -Xmn 堆内新生代的大小。通过这个值也可以得到老生代的大小:-Xmx减去-Xmn
  2. 永久代:Perm区。有的也将这个区划分到堆内存中。主要存放Class和Meta(元数据)的信息。在Java8中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。
  3. 栈空间:又名线程栈,运行时线程私有栈空间。
  4. 本地方法栈:C部分的代码区域。
  5. C Heap: 非java区域的内存使用,有些JNI的调用也会用到堆内存。
  6. PC计数器:存放当前线程所执行的字节码的行号,也是字节码地址。
java GC
  1. MinorGC:又称youngGC。当Eden区域满了,执行MinorGC。第一次MinorGC,就是找出Eden区域中活着的对象放入S0或者S1区域中。假设选择了S0,则Eden中的活着对象会被拷贝到这个区中,并清空Eden区,该过程称之为标记复制。当S0区域放不下的时候,剩下的或者对象直接存放到Old区中。第2次MinorGC,会将Eden中新创建的并且活着的对象加上S0中活着的对象,拷贝到S1中,如果放不下也会放到Old区中。然后清空Eden和S0区。往后,以此类推。当一个对象被MinorGC15次后还存活,则进入老生代。为什么是15,因为该标志位就只有4位,最大值为1111(15);
  2. Full GC:
    触发时刻:
    (1)调用System.gc时,系统建议执行Full GC,但是不必然执行
    (2)老年代空间不足
    (3)方法区空间不足
    (4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存
    (5)MinorGC中,S区存放不下活着的对象,需转存到老年代,但老年代的可用内存不够
    危害:
    (1)可能会导致Class、Method元信息的卸载
    (2)old区域比较大,故时间开销比较大
    (3)需要清理内存碎片,可能出现为了几个字节的碎片而移动几百MB的对象。
    总结,就是虽有有FullGC,但是我们不想看到它,甚至希望它永远不要发生。
什么是活着的对象,怎么区分?

凡是从根引用出发,能级联到的对象都被认为是活着的对象。那什么是根呢?“本地变量引用”、“操作数栈引用”、“PC寄存器”、“本地方法栈引用”、“静态引用”等。本地方法在一些内部调用中,在生命周期内依然是生效的,如new Thread().start(),虽然没有引用指向这个Thread,但是只要线程没有结束,这个对象就会一直存在。