JVM内存结构及java相关基础知识

本文详细解析了Java虚拟机(JVM)的基本组件,包括JVM、JRE和JDK的区别,以及Java内存区的组成,如方法区、Java堆、Java栈、PC寄存器和本地方法栈。重点解释了String对象为何被认为是不可变的,通过实例展示了String对象在内存中的操作过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.      JVM , JRE和JDK

JVM:加载class文件并进行解析

JRE(java running environment):JVM+API (java核心类库)

JDK:JRE+工具(包括javacjavadoc等工具)

2.      java内存区

包括方法区、java堆、java栈、PC寄存器、本地方法栈。

方法区(或者叫永久代permanent generation):包括类信息、方法信息(如一些private修饰之类的)、常量池、静态变量和class loader的引用。常量池指的是在编译期被确定,并被保存在.class文件中的一些数据。所以如果可以从常量池中取就不要去new一个。如Integeri=Integer.valueOf(10)会比Integer i=new Integer(10)好。这部分数据是所有线程共享的。

 

java堆:存放对象实例,所有的实例和数组都是在堆上分配的。Java堆和方法区一样是被所有线程共享的。Java堆有更细致的划分:新生代(采用minor gc)、老龄代(采用full gc),无论对java堆如何划分都是为了更好的回收内存,或更快的分配内存。根据VM Spec的要求,java 堆可以处于内存上不连续的空间,只要逻辑上连续即可。如果在堆中无法分配内存将会报OutOfMemeryError。

 

Java栈:存了很多栈帧。一个栈帧对应了java中的方法。栈帧包括局部变量、操作数栈(对数据的计算操作)、栈数据区(存放异常信息和解析静态变量--与方法区沟通)。每个方法被执行的时候都会创建一个栈帧,一个方法的调用至完成对应了栈帧的入栈至出栈过程。默认的栈大小是128K,可以手动配置。如果线程请求(比如线程栈1中的age是10,线程栈2的age是20)的栈深度大于栈大小,将抛出StackOverflowError。

 

PC寄存器:每个java线程都有一个PC寄存器用于保存程序执行到哪一个指令,对于非native的方法,这个区域记录的是正在执行的地址。

 

本地方法栈:为本地使用的方法服务,与java栈作用相同。会先去找本地方法接口,再通过本地方法接口调用本地方法,这里就体现了JVM的跨平台,本地方法接口可以有不同的实现。

3.      结合JVM内存,解释为什么在java中,说String是不可变的。

比如String s =new String(“wo”);String s1 = new String(“de”);

s = s + s1;

首先系统在堆上new出一个数组来存放“wo”,在栈中有个变量s指向堆中的“wo”对象,栈中的s1指向“de”对象;当执行s=s+s1时,系统重新在堆中new出一个更大的数组对象,然后将“wo”和“de”都复制进去,然后栈中的s指向这个新的对象。所谓的不可变是指:它没有在原数组“wo”上进行修改,而是新建了个更大数组进行扩展,也就是说,这时候堆里还是有“wo”这个对象数组存在的,只不过这个时候"s"变量不在指向"wo"这个数组了,而是指向了新new出来的数组,这就是和StringBuffer的区别,后者是在原数组上进行修改,改变了原数组的值,StringBuffer不是通过新new一个数组去复制,而是在原数组基础上进行扩展...再让变量指向原数组。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值