电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

JVM运行时内存空间结构


发布日期:2023/10/30
 

JVM执行Java程序的过程中管理的内存空间包括下列几个区域

程序计数器(Program CounterRegister)

· 线程私有占用空间很小

· 线程所执行代码行号指示器

· 解释器通过计数器的值选择下一条执行的字节码指令

· 线程执行Native方法时值为空

· 没有OOM(OutOfMemory)Java虚拟机栈(Java Virtual Machine Stacks)

· 线程私有· 储存方法栈帧(Stack Frame)

· 栈帧储存局部变量表操作栈动态链接方法出口等

· 局部变量表编译器可知的基本类型对象引用和returnAddress(字节码指令的地址)在编译期间完成分配运行时大小不变

· 存在StackOverflowError和OOM

· StackOverflowError线程请求栈深度大于VM允许深度

· OOM创建线程或扩展线程空间时无足够内存

StackOverflowError例子

/**

* Xssk

*

* @author Alfred Xu <>

*

*/

public class StackSOF {

int recursionLength;

void recusion() {

recursionLength++;

recusion();

}

public static void main(String[] args) {

StackSOF sof = new StackSOF();

try {

sofrecusion();

} catch (Throwable e) {

Systemoutprintln(sofrecursionLength);

eprintStackTrace();

}

}

}

OOM例子

/**

* Xssm

*

* @author Alfred Xu <>

*

*/

public class StackOOM {

static class Tester extends Thread {

@Override

public void run() {

try {

Threadsleep( * );

} catch (InterruptedException e) {

eprintStackTrace();

}

}

}

public static void main(String[] args) {

for (int i = ;; i++) {

new Tester()start();

Systemoutprintln(i);

}

}

}

本地方法栈(Native MethodStacks)

· 线程私有类似虚拟机栈

· 服务Native方法

· 同样存在StackOverflowError和OOM

· Hotspot中将Java虚拟机栈和本地方法栈合二为一通过Xss设置大小JDK以前默认K默认M

Java堆(Java Heap)

· 所有线程共享

· 储存对象实例

· GC和OOM的主要区域

Heap OOM例子

/**

* Xmsm Xmxm

*

* @author Alfred Xu <>

*

*/

public class HeapOOM {

public static void main(String[] args) {

List<Long> list = new ArrayList<Long>();

for (long i = ;; i++) {

listadd(i);

Systemoutprintln(i);

}

}

}

方法区(Method Area)

· 又叫非堆(NonHeap)对应HotSpot的永久代(Permanent Generation)

· 所有线程共享

· 储存VM加载的类信息常量静态变量JIT编译代码等

· 也有OOM一般是由于大量使用反射生成class

· 包含运行时常量池(Rumtime ConstantPool)

常量池溢出例子

/**

* XX:MaxPermSize=m

*

* @author Alfred Xu <>

*

*/

public class ConstantPoolOOM {

public static void main(String[] args) {

List<String> list = new ArrayList<String>();

for (int i = ;; i++) {

listadd(StringvalueOf(i)intern());

Systemoutprintln(i);

}

}

}

本机直接内存(Direct Memory)

· 不受VM直接管理但也有OOM

· 和NIO中的DirectByteBuffer相关

· 默认和Java堆大小一致

例子

/**

* XX:MaxDirectMemorySize=m

*

* @author Alfred Xu <>

*

*/

@SuppressWarnings(restriction)

public class DirectMemoryOOM {

static final int _MB = * ;

static void unsafeAllocate() throws IllegalArgumentException

IllegalAccessException {

Field unsafeField = UnsafeclassgetDeclaredFields()[];

unsafeFieldsetAccessible(true);

Unsafe unsafe = (Unsafe) unsafeFieldget(null);

List<Long> list = new ArrayList<Long>();

for (int i = ;; i++) {

long l = unsafeallocateMemory(_MB);

listadd(l);

Systemoutprintln(i);

}

}

static void byteBufferAllocate(boolean direct) {

List<ByteBuffer> list = new ArrayList<ByteBuffer>();

for (int i = ;; i++) {

ByteBuffer bb;

if (direct) {

bb = ByteBufferallocateDirect(_MB);

} else {

bb = ByteBufferallocate(_MB);

}

listadd(bb);

Systemoutprintln(i);

}

}

public static void main(String[] args) throws IllegalArgumentException

IllegalAccessException {

byteBufferAllocate(true);

// unsafeAllocate();

}

}

Hotspot Java内存空间结构

新生代(Young Generation)

大部分的对象的内存分配和回收在这里完成

Eden

新建的对象分配在此minor GC后被清空

Survivor

存储至少经过一次GC存活下来的对象以增大该对象在提升至老生代前被回收的机会

From Space

在minor GC后被清空GC后存活的对象放入老生代

To Space

Eden中在新生代GC后存活的对象放在此

老生代(Old Generation)

多次GC后存活的对象或者新生代放置不下的大对象

永生代(PermanentGeneration)

方法区

上一篇:获取运行中的JVM系统属性

下一篇:JVM中垃圾收集技术的变更