先上个图
这是根据《Java虚拟机规范(第二版)》所画的jvm内存模型。
- 程序计数器:程序计数器是用来记录当前线程方法执行顺序的,对应的就是我们编程中一行行代码的执行顺序,如分支,跳转,循环,异常处理等。所以在多线程下,程序计数器必然是线程隔离的,每个线程都有自己独立的程序计数器。注意,Java虚拟机中的程序计数器指向正在执行的字节码地址。
- 本地方法栈:本地方法栈时用来保存本地方法,即jvm调用外部的方法,比如操作系统本身的方法,或者自定义的c方法,这类方法都带有native关键字。这类又被成为java native interface。
- 虚拟机栈:也就是我们常说的栈,虚拟机栈时线程私有的,当虚拟机执行到一个方法时,就会在当前线程所在的栈中创建一个栈帧,栈帧用于存储局部变量、操作栈、动态链接、方法出口等信息。因此我们在方法中定义的一些基本变量,和引用变量都会存在栈中。
- 堆:堆是jvm内存区域最大的区域,堆被所有线程共享,几乎所有的实例对象都保存在堆中,所以堆也是垃圾收集器管理的主要区域,细分下堆还分为 eden区域,from survivor区域,to survivor区域。这个比较复杂,之后在详细说明。
- 方法区:又称 永久代,和堆类似,用于存放对象实例、以及class类信息、常量、静态变量、以及及时编译后的代码信息。这个区域也是所有线程共享的,也会有垃圾回收。实际上方法区只是一种概念,方法区本身也是堆的一部分,换句话说,方法区是在堆里面的,这也是人们常把jvm简单分为堆和栈的原因。但是在java8中,已经把永久代改为了元数据区(metaspace),元数据区使用的是本地内存(操作系统的内存),主要存储的类的元数据(class信息,代码信息等)。而常量,静态变量依然存在堆中。如下图
- 常量池:常量池是方法区的一部分,储存着常用,比如加了final关键字,或者字符串。占用的是堆中的一部分。因此以下代码也会报OOM
int i=0; while(true){ new String(i++).intern(); }
本文借鉴
深入理解Java虚拟机-----周志明著
终于总结好了---
原文地址:https://www.cnblogs.com/duangL/p/11575039.html
时间: 2024-10-29 12:08:42