Java虚拟机内存模型简介

 2019-12-10 16:18  阅读(1090)
文章分类:Java Core

一、Java技术体系 (Write Once,Run Anywhere)

1.1 Java程序设计语言

1.2 各种硬件平台上的Java虚拟机

1.3 class文件格式

以上三部分统称为JDK

1.4 Java API类库

1.5 来自商业机构和开源社区的第三方java类库

二、Java 虚拟机的发展史

2.1 Sun Classic VM (只能使用纯解释器方式来执行java代码、java语言很慢形象从这开始的)

2.2 Exact VM(具备现代高性能虚拟机的雏形,两级即时编译器、编译器和解释器混合工作模式、准确式内存管理能够让虚拟机能够识别内存中的数据类型)

2.3 HotSpot (Sun JDK和Open JDK中所带的虚拟机,目前使用最广泛的虚拟机,这款虚拟机有优秀的JIT编译理念和实际使用效果,因此sun公司收购了拥有这款虚拟机的公司,当然后来sun也被Oracle被收购了,天下风云、大多类似。。。。)

2.4 JRockit (曾经号称”世界上速度最快的java虚拟机”,属于BEA公司的虚拟机(其实也买了别的公司的),最后北Oracle收购了,因此Oracle有两款优秀的java虚拟机)

2.5 J9 (属于IBM公司,它与HotSpot的市场定位比较相近)

2.6 Azul VM 和 BEA Liquid VM 这类特定硬件平台专有的虚拟机才是“ 高性能” 的武器

三、Java 趋势

模块化 、多语言化(一个项目中并行处理用Clojure语言编写、展示层使用JRuby/Rails、中间层用java语言编写,最后运行在同一个虚拟机上)、多核并行(Fork/Join模式是处理并行编程的一个经典方法、java8支持Lambda,这个改善java对于函数式编程的的支持、而函数式编程的程序天然适合并行运行)、语法更加丰富、出现64位架构的虚拟机

20191210001719\_1.png

4、自动内存管理机制

线程公有:方法区、堆

线程私有:虚拟机栈、本地方法栈、程序计数器

20191210001719\_2.png 程序计数器:是一块较小的内存空间,它可以看作是当前线程线程所执行的字节码的行号指示器

Java虚拟机栈:是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame[ 1]) 用于存储局部变量表、操作数栈、动态链接、方法出口等信息。 每一个方法从调用直至执行完成的过程, 就对应着一个栈帧在虚拟机栈中入栈 到出栈的过程。如果线程请求的栈深度大于虚拟机所允许的深度, 将抛出StackOverflowError异常; 如果虚拟机栈可以动态扩展( 当前大部分的Java虚拟机都可动态扩展, 只不过Java 虚拟机规范中也允许固定长度的虚拟机栈), 如果扩展时无法申请到足够的 内存, 就会抛出OutOfMemoryError 异常。

本地方法栈:服务于虚拟机使用到的Native方法服务,HotSpot虚拟机甚至将本地方法栈和虚拟机合二位为一;与虚拟机栈一样,抛出StackOverflowError和OutOfMemoryError异常

java 堆:在虚拟机器启动时创建,用于存在对象实例,随着JIT编译器的发展与逃逸分析技术的主键成熟,对象实例都分陪在堆上也渐渐变得不是那么”绝对”了。现在收集器基本都采用分代收集算法,所以JAVA堆中的对象细分:新生代、老年代,空间区域可细分:Eden空间、From Survivor空间、To Survivor空间(Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可),这部分内存是可以进行扩展的(-Xmx和-Xms控制) 如果对中没有内存完成实例分配且堆也无法扩展、抛出OutOfMemoryError异常

方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据;根据java虚拟机规范的规定,当方法区无法满足内存分配需求时,讲抛出OutOfMemoryError异常

运行时常量池:它是方法区的一部分,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。除此之外,运行期间也可能将新的常量放入池中,比如String类的intern()方法。当常量池无法申请到内存时候会抛出OutOfMemoryError异常

直接内存:它并不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域,这部分内存也被频繁的使用,而且也可能导致OutOfMemoryError异常,比如Java1.4中引入的NIO,采用基于通道(channel)和缓冲区(Buffer)的I/O方式。它可以使用Native函数库直接分配堆外内存,然后通过在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。基于总内存的限制,在设置-Xmx时候,一定要考虑直接内存占用总内存的因素,否则会内存区域总和大于物理内存大小,从而导致动态扩张时候出现OutOfMemoryError异常。

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> Java虚拟机内存模型简介

相关推荐