####jdk分区
-
方法区
-
heap(堆)
-
程序计数器
指向当前线程正在执行的字节码指令地址(行号,记录行号原因:线程会切换等)
-
虚拟机栈
存储当前线程运行方法时所需的 数据、指令、返回地址
-
本地方法栈
用native修饰的方法
####详细
-
什么 是栈
栈是一种数据结构,用来存储数据
-
虚拟机栈
first in last out(先进后出) ,栈的基础单位:栈帧,
一个方法,一个栈帧;
如果是一个递归方法,栈帧就有n个,直到outstockoverflowexception异常,有几个栈帧和方法个数有关,和方法的出口无关
-
####heap
heap分为新生代、老年代、永久代
新生代分为eden区(8m)、s0区(1m)、s1区(1m)
当在 堆中申请内存时,首先会在eden区申请,如果小于8m,直接存在eden区,后面再有申请内存的时候,会先判断eden区是否 够装,如果不够,会先把eden区的内存放在s0区(如果够装下),eden、s0都装不下,会放进老年代,同时进行minor GC,进行eden、s0区的垃圾回收(全部清空),下次eden区放不下,会放进s1区,eden、s1都装不下,再次进行 minor GC,始终s0、s1 会有一个区是空的;
一个对象不会同时出现在2个不同的区中,不会这边沾一点、那边占一点
####网上资料
-
young空间
-
Eden 区默认会存放了 通过new或newInstance()等创建的对象
-
2个Survivor区通常称为S0、S1,理论上2个区是一样大的(如果有其他参数配置外)
-
-
Eden区和Survivor如何配合工作的:
-
不断创建对象的过程中,Eden区域会被装满,满的时候就开始做Young GC(也称为Minor GC),在Young空间第1次 GC的时候,会找出Eden区域存活的对象,并将这些对象存放到S0或S1区域中的一个中去
-
假设第1次 GC选择了S0存放对象,如果S0的空间放满了,剩下的对象就会放到Old区去。然后Eden区将会被清空。此时S1区域是空的。
-
第2次 Eden区满的时候,就会将 Eden区和S0区中存活的对象一起迁移到S1区域中(如果S1放不下,则会放到Old区),最后清空Eden区和S0区。此时S0就会成为空的。
-
以后的操作依次类推,在这个过程中,S0、S1始终有一个是空的。
-
结论: - 在Young空间清理的时候,由于活下来的对象是少数,所以寻找这些对象就会很快。 - 存活的对象不多,所以存放它们需要的空间也不大,所以就有了Survivor区域,也不会太大 - 如果对象的存活周期很长,程序跑得很慢,被清理的概率就会很低,Survivor区域放不下时就会放在Old区域
-
-
old区(老年代)
-
老年代,里面存放的都是在minor GC 时,young区存放不下,放在这里面的
-
在老年代满的时候,会进行 FULL GC,对old区进行清理,通常会做压缩碎片的操作,碎片也就是清除对象时产生的。如果活着的对象越多,那么整理碎片也会越麻烦(因为是顺序移动)
-
full gc的同时肯定有minor gc,因为是young存不下,先判断old中是否能放下,放不下进行full gc,能放下,直接放进old中;
-
-
permGen(永久代)
-
Class加载是被加载到了PermGen中(永久代中最大用户)
-
常量池(比如String对象的intern()方法会在常量池中查找相同值,找到了就直接返回,没找到就会存一个String对象在常量池中)
-
1.8以下才存在,>=1.8中没有了,变为了meta space元空间,元空间的大小是无限增大的,直到内存不够 ,服务器‘’爆‘’掉,所以一般还是设置下meta space最大的空间大小,并且meta space 并不是存放在堆中
-
-
理解有误的,请指出