美文网首页
java虚拟机学习笔记1-----java内存区域

java虚拟机学习笔记1-----java内存区域

作者: 乘风遇见 | 来源:发表于2017-12-10 12:58 被阅读0次

本文内容是笔者看了 《深入了解java虚拟机》后的一些笔记,也欢迎各位java爱好者一起学习和交流。

    java虚拟机在执行java程序的过程中会将他所管理的内存划分为若干个不同的数据区域,他们的用途、生命周期都不相同。分为以下数据区:

运行时数据区

1.程序计数器:虚拟机在启动时,会创建多个线程去执行任务,而由于cpu是在快速的上下文切换,而为了线程切换后能恢复倒正确的执行位置,就需要记录线程当前执行的位置,这个就是由程序计数器来完成的,所以程序计数器是每个线程所独有的。

 程序计数器可以看作是当前线程执行的字节码的行号指示器,字节码的解释工作就是通过改变这个计数器的值来选取下一条执行的字节码指令,分支、循环、跳转、异常处理等都需要依赖程序计数器来完成。

2.java虚拟机栈(线程栈):java虚拟机栈也是线程私有的,与线程生命周期相同,描述的是java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数帧、动态链接、方法出口等信息,每个方法从调用直至执行完成的过程,就对应着一个栈帧从入栈到出栈的过程(出栈后这个栈帧即被销毁)。(在创建一个线程后,默认给其分配1M的内存空间,也就是我们常说的线程栈)

局部变量表:存放了编译期可知的各种基本数据类型(boolean、int..)、对象引用类型(指向堆区的对象)和returnAddress类型(指向了一条字节码指令的地址)。

对虚拟机栈这个区域规定了两种异常情况:1.如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverFlowError异常;2.如果虚拟机栈可以动态扩展,当扩展无法申请到足够的内存时就会抛出OutofMemoryError异常。

3.本地方法栈:与虚拟机栈所发挥的作用相似,他们之间的区别不过是虚拟机栈为虚拟机执行java方法(也就是字节码服务),而本地方法栈则为虚拟机使用倒的native方法服务。线程私有。

相信有部分读者和我一样,也不懂这个 native method是什么,有什么作用,查了下资料说:1.navive method是java方法调用非java方法,比如有一些方法是由C、C++来实现的,可以告知编译器去调用这个方法,而本地方法库应该就是由这些native method组成的,为什么要使用native method呢? 2java使用起来非常方便,然而有些层次的任务用java实现起来不容易,或者我们对程序的效率很在意时,问题就来了。

与java环境外交互:

有时java应用需要与java外面的环境交互。这是本地方法存在的主要原因,你可以想想java需要与一些底层系统如操作系统或某些硬件交换信息时的情况。本地方法正是这样一种交流机制:它为我们提供了一个非常简洁的接口,而且我们无需去了解java应用之外的繁琐的细节。

与操作系统交互:

JVM支持着java语言本身和运行时库,它是java程序赖以生存的平台,它由一个解释器(解释字节码)和一些连接到本地代码的库组成。然而不管怎 样,它毕竟不是一个完整的系统,它经常依赖于一些底层(underneath在下面的)系统的支持。这些底层系统常常是强大的操作系统。通过使用本地方法,我们得以用java实现了jre的与底层系统的交互,甚至JVM的一些部分就是用C写的,还有,如果我们要使用一些java语言本身没有提供封装的操作系统的特性时,我们也需要使用本地方法。

更多关于native method的内容请前往这里:blog.csdn.net/wike163/article/details/6635321

4.java堆:java堆(java heap)是java虚拟机所管理的内存中最大的一块,被所有线程共享的一块区域,在虚拟机启动的时候创建,此内存区域的唯一目的就是存放对象实例(线程栈中栈帧存放的局部变量中存放对象的引用),几乎所有的对象实例都在这里分配内存(在java虚拟机规范中描述的是:所有的对象以及数据都在堆上分配,但随着JIT编译器的发展,这个规范也不是绝对的)

java堆是垃圾回收器管理的主要区域(也称新生代),从内存回收的角度来看,由于线程收集器都采用分代算法,所以java堆中还细分为新生代、老年代。细分还有许多区域,但无论怎么划分都是为了更好的回收内存,而堆只存储对象的实例。根据java虚拟机的规范:java堆可以处于物理上不连续的内存空间中,只要逻辑上连续即可。

5.方法区:与堆一样也是线程共享区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,他有一个别名:no-heap,非堆,和堆区分开。(比如有一个静态对象,他的引用是在静态变量中,不在局部变量表中,对象实例存在堆中),相对而言垃圾收集行为在这个区域是比较少出现的。但并非数据进入方法区后就如永久代的名字一样永久存在了,这区域内存回收的主要目标是针对常量池的回收和内存的卸载,条件相当苛刻,但回收是有必要的。

6.运行时常量池:是方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容在类加载后进入方法区的运行时常量池中

运行时常量池相对于Class文件常量池的另外一个重要特征就是具备动态性,java语言并不要求常量一定只有编译期产生,也就是并非预置入Class文件中常量池的内容才能进入方法区的运行时常量池,运行期间也可以将新的常量放入池中,比如String的intern()。

int i = 1;把整数1赋值给int型变量i,整数1就是Java字面量,同样,String s = "abc";中的abc也是字面量。

7.直接内存:并不是运行时数据区的一部分,也不是java虚拟机规范定义的内存区域,但这部分内存被频繁使用,JDK1.4新加入的NIO类中可以使用native直接分配堆外内存,然后通过存储在java堆中的DirectByteBuffer对这块内存的引用进行操作,这样避免了java堆和native堆来回复制数据。她属于本机内存。

当它本可进取时,却故作谦卑;

当它在空虚时,用爱欲来填充;

在困难和容易之间,它选择了容易;

它犯了错,却借由别人也会犯错来宽慰自己;

它自由软弱,却把它认为是生命的坚韧;

当它鄙夷一张丑恶的嘴脸时,却不知那正是自己面具中的一副;

它侧身于生活的污泥中,虽不甘心,却又畏首畏尾。

相关文章

网友评论

      本文标题:java虚拟机学习笔记1-----java内存区域

      本文链接:https://www.haomeiwen.com/subject/khwmixtx.html