您的位置:首页 > 编程语言 > Java开发

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

2012-03-10 21:16 555 查看
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一个数组去复制,而是在原数组基础上进行扩展...再让变量指向原数组。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: