标签:werror 一个栈 lang tla 生成 private top 引用 过程
1. 程序计数器
行号指示器,线程私有,本地方法计数器值为null。
2. java虚拟机栈
存储局部变量、方法等信息。每一个方法被调用至执行完毕的过程就对于着一个栈帧从入栈到出栈的过程,进入一个方法时,这个方法需要在栈帧中分配多少空间是完全确定的,运行期间不会改变。栈是线程私有的。
3. 本地方法栈
作用类似于Java虚拟机栈,主要用于存放本地方法的变量。线程私有。
4. java堆
所有线程共享,虚拟机启动时创建,唯一的目的就是存放对象实例,几乎所有对象实例都在这分配内存。堆是垃圾收集器管理的区域,空间可以是固定大小的,也可以是可扩展的。
5. 方法区
所有线程共享,主要用于存储被虚拟机加载的类型信息、储常量以及静态变量等,java6之后放弃永久代,逐步使用本地内存实现方法区。方法区较少发生垃圾收集行为。
6. 运行时常量池
是方法区的一部分,存放编译期生成的各种字面量和符号引用(常量池表),具有动态性,运行期间也可以将新的常量放入池中。
主要流程:new -> 类加载检查 -> 分配空间 -> 内存空间初始化 -> 构造函数 -> 创建完成
对象在堆内存中的存储布局可划分为三个部分:对象头/实例数据/对齐填充
java程序通过栈上的reference操作堆上的具体对象。对象的访问方式由虚拟机的实现而定。主流的访问方式有两种:句柄访问/直接指针。
1. java堆溢出
/**
* java.lang.OutOfMemoryError: Java heap space
* java堆溢出
*/
class HeapOOM {
static class OOMObject {
}
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<>();
while (true) {
list.add(new OOMObject());
}
}
}
2. java栈溢出
/**
* java.lang.StackOverflowError
* java栈溢出
*/
class JavaVMStackSOF {
private int length = 1;
public void stackLeak() {
length++;
stackLeak();
}
public static void main(String[] args) {
JavaVMStackSOF stackSOF = new JavaVMStackSOF();
try {
stackSOF.stackLeak();
} catch (Throwable e) {
System.out.println(stackSOF.length);
throw e;
}
}
}
3. 创建线程导致内存溢出
class JavaVMStackOOM {
private void dontStop() {
while (true) {
}
}
private void stackLeakByThread() {
while (true) {
Thread thread = new Thread(() -> dontStop());
thread.start();
}
}
public static void main(String[] args) {
JavaVMStackOOM stackOOM = new JavaVMStackOOM();
stackOOM.stackLeakByThread();
}
}
4. 运行时常量池溢出
class RunTimeConstantPoolOOM {
public static void main(String[] args) {
/**
* java6运行会出现常量池OOM,7之后运行会出现堆溢出
* 因为7之后,存放在永久代的字符串常量池移至java堆中
*/
/*Set<String> set = new HashSet<>();
short i = 0;
while (true) {
set.add(String.valueOf(i).intern());
}*/
/**
* java6中,intern方法把首次遇到的字符串实例复制到永久代的字符串常量池,而StringBuilder创建的对象存储在堆上,不是同一个引用,返回false,false,false
* java7中,字符串常量池已经移至堆中,所以intern()返回的引用和StringBuilder创建的对象是同一个,返回true,false,false,
* 二三句返回false因为Builder.toString()之前常量池已经有它的引用
*/
String str1 = new StringBuilder("计算机").append("软件").toString();
System.out.println(str1.intern() == str1);
String str2 = new StringBuilder("ja").append("va").toString();
System.out.println(str2.intern() == str2);
String str3 = new StringBuilder("计算机").append("软件").toString();
System.out.println(str3.intern() == str3);
}
}
标签:werror 一个栈 lang tla 生成 private top 引用 过程
原文地址:https://www.cnblogs.com/youtang/p/12642111.html