JVM内存管理运行时数据区域分为:方法区、虚拟机桟、本地方法桟、堆、程序计数器、常量池;
JVM与外界交互:调用执行引擎====》本地库接口====》本地方法库;
程序计数器:分支、循环、跳转、异常处理,线程切换都依赖此计数器,此区域不会出现内存溢出异常;
虚拟机栈:也是线程私有,也是字面上常说的栈内存,通常所指存放boolean、byte、char、short、int、float、long、double、
对象指针引用,对象起始地址指向等,JVM中存在固定长度的栈,当线程所消耗的栈深度超过了固定长度,会出现栈内存溢出异
常,JVM也可允许存在动态长度的栈;
本地方法栈:与虚拟机栈大致相同,区别在于本地方法栈执行Java方法执行本地native方法;
堆:JVM内存最大的一块,被所有线程共享,也是垃圾回收器主要管理的一个区域,基本分为分代收集算法,分为新生代和老年
代,再细分From survivor(生存者)、To survivor(生存者) 、Eden空间,可以处于物理不连续的内存空间,可以是固定大小,也可
以是动态扩展,主流虚拟机通过 -Xms:初始堆大小 -Xmx:最大堆大小来动态扩展,若堆内存没完成实例分配,也无法再扩
展,则会抛出内存溢出异常;另外:-Xmn:新生代堆大小 -Xss:每个线程的栈大小 注意:-Xms设置初始值不宜过大,原因是
会影响JVM性能,具体是虽然GC回收方法执行频率会降低,但也加长了每次GC运行时间,所有用户线程停止工作,也就是Java
程序不工作;当堆区不足时,新生区变为老年区,剩余(相当于老年区变大了)老年区大小: -Xmx减去-Xmn;
方法区(JDK8变名为元数据区):是线程共享的区域,别名叫非堆,很多人称之为永久代,由于回收条件苛刻,通常是对于常量池的回收和类型的卸载,
当方法区无法满足内存需求分配是,会将抛出内存溢出异常。
运行常量池:此区为方法区的一部分,Class字节码中包含类的版本、字段、方法、接口,还有一项是常量池,通常存放直接引
用,符号引用,运行常量池受方法区制约,当常量池无法分配内存,将抛出内存溢出异常;
直接内存:这部分区域并不是虚拟机运行时内存区域一部分,但是这部分区域被频繁使用,也可能导致内存溢出;虽然大小不受
堆内存大小限制,但会受本机总内存限制;如果各区域所需内存总和大于总物理内存,则会抛出内存溢出异常;