方法区
1供各线程共享的运行时内存区域,储存了每个类的构造信息,例如常量池,字段和方法数据,构造函数和普通方法的字节码内容。小class在硬盘,大Class在方法区中
2方法区是规范,不同虚拟机不一样(实例变量在堆内存中,和方法区无关)
栈
栈负责运行,堆负责存储。
栈也叫栈内存,主管java程序运行,是在线程创建时候创建,声明周期跟随于线程周期,线程结束内存释放。栈不存在垃圾回收。8中基本类型变量 + 对象的引用变量+实例方法都是在函数的栈内存分配。
栈帧(压入栈的方法)主要保存三种数据
本地变量:输入参数,输出参数,方法内的变量
栈操作: 记录出入栈操作(类似pc计数器)
栈帧数据:类文件,方法等
每个方法执行的时候都会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法从调用到执行完毕的过程,就对应着一个栈帧在虚拟机中入栈到出栈的过程。栈的大小通常在256kb到756kb
递归太多造成StackoverFlowError
Car car1 = new Car();
Car car2 = new Car();
reference指的是 car1 car2 Car是大Class存在于方法区之中 new的两个东西在堆中(堆存放的是元数据,也就是描述数据的数据)
堆
一个JVM实例中只存在一个堆内存,堆内存的大小是可以调节的。类加载器读取了文件后,需要把类,方法,场变量放在堆内存当中,保存搜友引用类型的真实信息,以方便执行器执行,堆内存分为三部分:
新生区
伊甸区
幸存0区(from)
幸存1区(to)
伊甸满了。轻GC MinorGC。
养老区满了。重GC。
养老区重GC没用,OOM。
新生eden区是类诞生成长消亡的区域,一个类在着产生,应用最后被垃圾回收器手机,结束声明。新生去分为两部分:伊甸区和幸存者区。幸存者区又分为两部分:0区和1区。当伊甸区空间快用完,将触发垃圾回收,将伊甸中不被其他对象引用的对象进行销毁,然后移动到1区,1区快满了移动到养老区。养老区快满了触发GC清理养老区。如果还是快满了,报OOM(OutOfMemoryError)异常。如果OOM堆空间异常,可能是堆内存大小设置不够可以通过设置-Xms, -Xmx来调整,也可能确实存在不能被回收的大量对象。
from区和to区的位置不固定,GC之后有交换,谁空谁是to。Eden from to 比例是8:1:1。新生养老 1:2。
MinorGC (复制 》清空》互换)
1 eden幸存,from复制到to, 年龄+1
当eden区满会触发第一次GC,把还活着的拷贝到from
eden再次触发GC会扫描eden和from区,幸存的拷贝到to,同时对象年龄+1
2 清空eden, from。这时候from空了
3 to和from互换 对象会在from和to之间来回复制,交换15次(MaxTenuringThreshold)后进入老年代
养老区
永久区(Java8后叫做元空间)
类似rt.jar会在永久区加载。常驻内存,用于存放JDK自身所携带的Class,Interface的元数据,存储的是运行环境必须的类信息,是不会被垃圾回收的,关闭JVM才会释放此区域的内存。