JVM内存结构

Java虚拟机在执行程序时定义了多种数据区,包括程序计数器、虚拟机栈、本地方法栈、堆和方法区。程序计数器记录下一条指令地址,是线程私有的,不会发生内存溢出。虚拟机栈服务于每个线程,存储栈帧,与方法调用对应。堆是所有线程共享的,有垃圾回收机制。方法区存储类的结构,如运行时常量池。文章还讨论了线程安全、内存溢出和不同JVM版本中方法区的变化。
摘要由CSDN通过智能技术生成
The Java Virtual Machine defines various run-time data areas that are used during execution of a program.

Some of these data areas are created on Java Virtual Machine start-up and are destroyed only when the Java Virtual Machine exits.

Other data areas are per thread.
Per-thread data areas are created when a thread is created and destroyed when the thread exits.

在这里插入图片描述

程序计数器

记录下一条JVM指令的地址
线程私有,每个线程都有自己的程序计数器
不会存在内存溢出
# Each Java Virtual Machine thread has its own pc (program counter) register.
# If that method is not native
# the pc register contains the address of the Java Virtual Machine instruction currently being executed.
# If the method currently being executed by the thread is native
# the value of the Java Virtual Machine's pc register is undefined. 

虚拟机栈

每个线程运行时所需要的内存,每个线程对应一个虚拟机栈
// Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread.
栈内由多个栈帧组成,栈帧(方法参数,局部变量,方法结束时的返回地址)对应着方法调用
每个线程运行时只能有一个活动栈帧,对应着当前正在执行的那个方法
// A Java Virtual Machine stack stores frames.

垃圾回收不涉及栈内存
方法内的局部变量是线程私有的,不会有线程安全问题
public class Demo {
	// 多个线程同时执行此方法
	static void m1() {
		int x = 0; // 每个线程都会有自己的虚拟机栈, x是线程私有的, 线程安全
		for(int i = 0; i < 5000; i++){
			x++;
		}
		System.out.println(x);
	}
	// 这个不是线程安全的,因为是从外面传过来的,外面也可以访问sb指向的对象
	// 可以使用StringBuffer代替
	static void m2(StringBuilder sb){
		sb.append(1);
		sb.append(2);
		System.out.println(sb.toString());
	}
	// 这个不是线程安全的,其他线程有可能拿到sb引用的对象
	// 方法执行完,sb变量(栈中)会被释放,但是指向的对象在堆中
	// 过段时间此对象还没有变量指向, GC才会清理此对象
	static StringBuilder m3(){
		StringBuilder sb = new StringBuilder();
		sb.append(1);
		sb.append(2);
		return sb;
	}
}
类的static变量是对多个线程共享的,会有线程安全问题

本地方法栈

调用native方法时,给native方法提供的内存空间

(程序计数器,虚拟机栈,本地方法栈)都是线程私有的
(堆和方法区)都是线程共享的
# The Java Virtual Machine has a heap that is shared among all Java Virtual Machine threads.
# The heap is the run-time data area from which memory for all class instances and arrays is allocated.

堆中有垃圾回收机制,堆中不再被引用的对象都会被释放
OutOfMemory(又称之为OOM)
java.lang.OutOfMemoryError:Java heap space(堆内存溢出)
java.lang.OutOfMemoryError:PermGen space(永久代\方法区溢出)

jps # 显示Java进程
jmap -heap pid # 显示这一时刻指定Java进程的堆空间情况
jmap -dump:format=b,file=fileName pid # 生成dump文件,保存了某一时刻JVM堆中对象使用情况
jmap -dump:live,format=b,file=c:\dump\heap.hprof pid # live指只转储堆中的活动对象
还可以使用jvisualvm工具(jdk8之后需要额外下载)

jmap命令使用详解
生成和查看dump文件
生成HeapDump

方法区

方法区所有线程共享
# The Java Virtual Machine has a method area that is shared among all Java Virtual Machine threads. 

它存储每个类的结构,如(运行时常量池,字段和方法数据),以及(方法和构造函数的代码),
包括在(类和实例初始化以及接口初始化)中使用的特殊方法.
# It stores per-class structures such as the run-time constant pool, field and method data
# and the code for methods and constructors, including the special methods (§2.9) 
# used in class and instance initialization and interface initialization.

尽管方法区在逻辑上是堆的一部分,但简单的实现可以选择不进行垃圾收集或压缩.
# Although the method area is logically part of the heap, simple implementations may
# choose not to either garbage collect or compact it.

方法区是规范
永久代和元空间都是它的实现
HotSpotJDK7及之前,永久代,在堆中
HotSpotJDK8及之后,元空间,移除到本地内存中了,常量池的StringTable一直都在堆中
javap -v Test.class # 显示class文件中的信息
javap -c Test.class # 对class文件进行反编译

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值