JVM 中内存模型
目录
其中:
线程私有的:程序计数器,虚拟机栈,本地方法栈
线程共享的:堆,方法区,直接内存
下面介绍每个区
线程共享区
- 方法区:存储虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据
哪些类信息?
类的版本
字段
接口
方法
运行时常量池(类似于hashset结构)
调用new创建对象,不考虑常量池,直接在堆中创建。
如果是常量,会从常量池中拿取,如果没有才分配。
方法区和永久代(Hotspot中对等,垃圾收集器扩展到了方法区),在虚拟机规范中不等价。public static void main(String[] args) { String s1 = "abc"; String s2 = "abc"; String s3 = new String("abc"); System.out.println(s1 == s2); //true System.out.println(s1 == s3); //false System.out.println(s1 == s3.intern()); //true,intern将分配的对象放到常量池中 }
垃圾回收器在方法区的行为(少见,回收效率低。比如常量池回收,对象类型的卸载)
异常的定义(内存溢出) -
堆:
存放对象实例
垃圾收集器管理的主要区域
新生代,老年代。
内存溢出
-Xmx:最大堆大小
-Xms:初始堆大小
线程独占区
- 虚拟机栈:(java方法执行的动态内存模型)
栈帧:每个方法执行都会创建一个栈帧。保存环境上下文(局部变量表,操作数栈,动态链接,方法出口)。
方法在进入后大小就不会改变了。局部变量表的内存空间在编译期间完成分配。动态创建的对象分配的是引用的大小。
如果栈中不能再放入栈帧,就会出现栈溢出。
虚拟机栈为虚拟机执行java方法服务
- 本地方法栈
类似虚拟机栈。Hotspot不区分这两个,合二为一了。
本地方法栈为虚拟机执行native方法服务
- 程序计数器
记录程序执行位置,没有内存溢出情况。本地方法记录地址,native方法为undefine