每个进程拥有一个JVM实例
一个JVM实例只存在一个堆内存,堆也是Java内存管理的核心区域
Java堆区在JVM启动的时候即被创建。其空间大小也就确定了。是JVM管理的最大的一块内存空间
《Java虚拟机规范》规定,堆可以处于物理上不连续的内存空间中,但是在逻辑上他应该是连续的
所有的线程共享Java堆,在这里还可以划分为线程私有缓冲区(Thread Local Allocation Buffer ,TLAB)
《Java虚拟机规范》中对Java堆的描述是:所有的对象实例以及数组都对应当在运行时分配在堆上
数组和对象可能永远不会存储在栈上,因为栈帧中保存引用,这个引用指向对象或者数组在堆中的位置
在方法结束后,堆中的对象不会马上被移除,仅仅在垃圾收集的时候,才会被移除
堆,是GC(Garbage Collection 垃圾收集器)执行垃圾回收的重点区域
测试代码 - 只用jdk自带的工具查看堆内存分析 在jdk的安装目录下的bin下的jvisualvm.exe工具
/**
* VM: -Xms10m -Xmx10m
*/
public class HeapDemo {
public static void main(String[] args) {
System.out.println("start...");
try {
TimeUnit.SECONDS.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end...");
}
}
/**
* VM: -Xms20m -Xmx20m
*/
public class HeapDemo1 {
public static void main(String[] args) {
System.out.println("start...");
try {
TimeUnit.SECONDS.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end...");
}
}
public class SimpleHeap {
private int id;
public SimpleHeap(int id) {
this.id = id;
}
public void show() {
System.out.println("my id is:" + id);
}
public static void main(String[] args) {
SimpleHeap s1 = new SimpleHeap(1);
SimpleHeap s2 = new SimpleHeap(2);
int[] arr = new int[10];
Object[] arr1 = new Object[10];
}
}
Java堆用来存储Java对象实例,那么堆的大小在JVM启动的时候就已经设定好了,可以通过选项设置 "-Xmx"和"-Xms"来进行设置 (设置的是年轻代+年老代的大小)
一旦堆区的内存大小超过 -Xmx 所指定的最大内存时,将会抛出 OutOfMemoryError异常
通过会将 -Xms 和 -Xmx两个参数设置为相同的值,为了能够在垃圾回收机制清理完堆区之后不需要重新分隔计算堆区的大小,从而提升性能
默认情况下
代码验证
public class HeapSizeDemo {
public static void main(String[] args) {
long initialMemory = Runtime.getRuntime().totalMemory();
long maxMemory = Runtime.getRuntime().maxMemory();
System.out.println("-Xms:" + (initialMemory / 1024 / 1024) + " M");
System.out.println("-Xms:" + (maxMemory / 1024 / 1024) + " M");
System.out.println("系统内存大小:" + (initialMemory * 64 / 1024 / 1024 / 1024) + " G");
System.out.println("系统内存大小:" + (maxMemory * 4 / 1024 / 1024 / 1024) + " G");
}
}
/**执行结果
* -Xms:245 M
* -Xms:3618 M
* 系统内存大小:15 G
* 系统内存大小:14 G
*/
常见的OOM和栈溢出已经总结到 Java基础篇/Java - 异常 - 进阶 - OOM异常.md
下面举例演示:Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
/**
* VM args: -Xms20m -Xmx20m
* Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
*/
public class HeapOomCase {
static class OomObject {
}
public static void main(String[] args) {
ArrayList<OomObject> list = new ArrayList<>();
while (true) {
list.add(new OomObject());
}
}
}
下面的参数在开发中一般不会调整
配置新生代老年代在堆结构的占比
在Hotspot中,Eden空间和另外两个Survivor空间缺省占比为8:1:1
当然开发人员可以通过选项 "-XX:SurvivorRatio"调整这个比例,如 -XX:SurvivorRatio=8
几乎所有的Java对象都是在Eden区被new出来的
绝大部分的Java对象的销毁都在新生代进行了
可以使用 ”-Xmn“ 设置新生代的最大内存大小
总结
/**
* VM args: -Xms20m -Xmx20m
*/
public class HeapOomCase {
static class OomObject {
}
public static void main(String[] args) {
ArrayList<OomObject> list = new ArrayList<>();
while (true) {
list.add(new OomObject());
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
对象提升(Promotion)规则
针对不同的年龄段的对象分配原则如下所示
为什么要有TLAB(Thread Local Allocation Buffer)
什么是TLAB
对象的分配过程
逃逸分析概述
如何将堆上的对象分配到栈,需要使用逃逸分析手段
这是一种可以有效减少Java程序中同步负载和内存堆分配压力的跨函数全局数据流的分析算法
通过逃逸分析,Java Hotspot编译器能够分析出一个新的对象的引用的适用范围从而觉得是否要将这个对象分配到堆上
逃逸分析的基本行为就是分析对象的动态作用域
快速判断是否发生逃逸分析
JDK 6u23版本之后,Hotspot中默认开启了逃逸分析
如果使用较早的版本
结论:开发中能使用局部变量的,就不要在方法外进行定义
**标量(Scalar)**是指一个无法在分解成更小的数据的数据,Java中的原始数据类型就是标量
相对的,哪些还可以分解的数据就叫做 聚合量(Aggregate),Java中的对象就是聚合量,因为可以分解为其他的聚合量和标量。
在JIT阶段,如果经过逃逸分析,发现一个对象不会被外界访问的话,那么经过JIT优化,就会把这个对象拆解成若干个成员变量来替代。这个过程就是标量替换
代码演示
public class Test {
public static void main(String[] args) {
alloc();
}
public static void alloc() {
Point point = new Point(1, 23);
System.out.println(point.x);
System.out.println(point.y);
}
}
class Point {
public int x;
public int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public class Test {
public static void main(String[] args) {
alloc();
}
public static void alloc() {
int x = 1;
int y = 23;
System.out.println(x);
System.out.println(y);
}
}
class Point {
public int x;
public int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。