内存管理

2018-01-28  本文已影响5人  维乾

线程共享区:方法区(运行时常量池)、堆内存、

线程独立区:程序计数器、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()将堆内存中的对象,放到了方法区中的运行时常量池中。

上一篇 下一篇

猜你喜欢

热点阅读