前言
人生中的第一篇博客,正好在学习架构课程,写博客是为了记录知识点方便自己以后复习巩固。由于本文是概述,所以大部分采用了周志明老师的《深入理解Java虚拟机》上的原文。
正文
一. JDK和JRE
我们可以把Java程序设计语言、Java虚拟机、Java类库这三部分统称为JDK(Java Development Kit),JDK是用于支持Java程序开发的最小环境。把Java类库API中的Java SE API子集和Java虚拟机这两部分统称为JRE(Java Runtime Environment),JRE是支持Java程序运行的标准环境。
二. Java从编译到执行
编译:一个Java 程序,首先经过
javac
编译成.class 文件。
加载:JVM将class文件加载到方法区,执行引擎将会执行这些字节码。
执行:翻译成操作系统相关的函数(机器码)。
三. Java虚拟机
JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
Java虚拟机主要分为五大模块:类装载器子系统、运行时数据区、执行引擎、本地方法接口和垃圾收集模块。
运行时数据区
Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。运行时数据区可以分为两大类:线程私有区域(每个线程都会在虚拟机中分配一块单独的内存空间)和线程共享区域(被所有的线程共享,且只有一份)。而它们各自具体的划分如下:
线程私有
(指令):程序计数器、虚拟机栈、本地方法栈
线程共享
(数据):堆、方法区
直接内存
JVM运行时会从操作系统申请大块的堆内存空间用于运行时数据的存储,同时还有虚拟机栈、程序计数器和本地方法栈内存(栈区),除此之外的本机剩余内存就叫直接内存(Direct Memory),亦可称之为堆外内存。它并不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。
在JDK 1.4中新加入了NIO
(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区 (Buffer)的I/O方式,它可以使用Native
函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer
对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据(例如两个Java程序要互相通讯,都要经过直接内存,如果是保存在直接内存中就可以共享数据)。
直接内存不受Java堆大小的限制,但是受本机总内存(包括物理内存、SWAP分区或者分页文件)大小以及处理器寻址空间的限制,可以通过-XX:MaxDirectMemorySize
来设置(默认与堆内存最大值一样)。
除了上述DirectByteBuffer引用堆外内存的方式外,其他堆外内存主要是使用了Unsafe和JNI方式直接申请的内存。
后记
本文是JVM学习的入门知识,简单概述了JVM内存空间的划分,在后续章节会详细介绍其中的运行时数据区。JVM官网地址:https://docs.oracle.com/javase/specs/index.html