线程共享区:方法区(运行时常量池)、堆内存、
线程独立区:程序计数器、java虚拟机栈、本地虚拟机栈、
1.程序计数器
1.程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。(就是指定代码执行的行号。)
2.程序计数器是处于线程独占区。
3.如果线程执行的是java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址。如果正在执行的是native方法(什么是native方法,参考(http://blog.csdn.net/zmx729618/article/details/50779924)),这个计数器的值为undefined。
4.此区域是唯一一个在java虚 拟机规范中没有规定任何OutOfMemoryError情况的区域。
// goto 可以执行程序计数器的功能,但现在已经不用了。 是保留字,java9不用,开发者也不能用,因为现在不用说不定以后就可以用了。
2.虚拟机栈
1.虚拟机栈描述的是java方法执行的动态内存模型。(对要执行的方法进栈出栈)
2.栈帧,每个方法执行,都会创建一个栈帧,伴随着方法从创建到执行完成。用于存储局部变量表,操作数栈,动态链接,方法出口等。
3.局部变量表,存放编译期可知的各种基本数据类型,引用类型,returnAddress 类。
局部变量表的内存空间在编译完成分配,当进入一个方法时,这个方法需要在帧分配多少内存是固定的,在方法运行期间是不会被改变局部变 量表的大小。
4.大小 可能会抛出stackOverflowError、OutOfMemoryError错误。
3.本地方法栈
1. 本地方法栈为虚拟机执行native方法服务。
2.虚拟机栈为虚拟机执行java方法服务。
4.堆内存
1.存放对象的实例(是内存管理最大的区域)(也不是所有的对象实例都会分配到堆内存区域,因为有些高级的优化可以不需要分配到堆内存区域)
2.垃圾收集器管理的主要区域
3.新生代,老年代,Eden空间。
4.有可能抛出OutOfMemoryError
5.修改堆内存大小的参数 -Xmx(最大空间) -Xms(最小空间)
5.方法区
1.存储虚拟机加载的类信息(类版本,字段,方法,接口),常量,静态变量,即时编译器编译后的代码等数据。
2.方法区和永久代
3.垃圾回收的方法区的行为。
4.有可能抛出OutOfMemoryError
6.运行时常量池
1.方法区的一部分,所有线程共享。虚拟机加载Class后把常量池中的数据放入到运行时常量池。
7.直接内存
1.直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用,而且也可能导致OutOfMemoryError异常出现(参考(http://blog.csdn.net/dustin_cds/article/details/50857727))
问题
1.test1==test2 为什么相等?
加载类时,局部变量test1、test2是放在虚拟机栈中。而它们的创建的字符串是放在方法区的运行时常量池中,且是在StringTable:HashSet的数据结构,遵循HashSet的特性,无序,不可重复。所以test1、test2指向实例的地址相同。
2.test1==test3为什么不相等?
加载类时,局部变量的test1和test3是放在虚拟机栈中,test3是通过new 创建对象的,它讲对象放在堆内存中。test1字符串的创建是放在方法区中的运行时常量池中。所以二者指向的地址不相等。
3.test1==test3.intern()为什么相等?
因为test3.intern()将堆内存中的对象,放到了方法区中的运行时常量池中。
网友评论