浅谈JVM及原理
前言
JVM一直是java知识里面进阶阶段的重要部分,如果希望在java领域研究的更深入,则JVM则是如论如何也避开不了的话题,本系列试图通过简洁易读的方式,讲解JVM必要的知识点。
运行流程
我们都知道java一直宣传的口号是:一次编译,到处运行。那么它如何实现的呢?我们看下图:

java程序经过一次编译之后,将java代码编译为字节码也就是class文件,然后在不同的操作系统上依靠不同的java虚拟机进行解释,最后再转换为不同平台的机器码,最终得到执行。这样我们是不是可以推演,如果要在mac系统上运行,是不是只需要安装mac java虚拟机就行了。那么了解了这个基本原理后,我们尝试去做更深的研究,一个普通的java程序它的执行流程到底是怎样的呢?例如我们写了一段这样的代码:
public class HelloWorld { public static void main(String[] args) { System.out.print("Hello world"); } }
这段程序从编译到运行,最终打印出“Hello world”中间经过了哪些步骤呢?我们直接上图:

java代码通过编译之后生成字节码文件(class文件),通过:java HelloWorld执行,此时java根据系统版本找到jvm.cfg,各位可以搜索一下自己电脑上的jvm.cfg文件在哪,它会根据你的系统版本放在不同的位置,比如我的这个文件就在:C:\Program Files\Java\jdk1.8.0_101\jre\lib\amd64\jvm.cfg,打开看一下:

这是我电脑上的文件,其中-server KNOWN就表示名称为server的jvm可用。如果这时你搜索一下你电脑上jvm.dll,你就会发现它一定在你的某个server目录下,比如我的:C:\Program Files\Java\jdk1.8.0_101\jre\bin\server\jvm.dll。简而言之就是通过jvm.cfg文件找到对应的jvm.dll,jvm.dll则是java虚拟机的主要实现。接下来会初始化JVM,并且获取JNI接口,什么是JNI接口,就是java本地接口,你想啊java被编译成了class文件,JVM怎么从硬盘上找到这个文件并装载到JVM里呢,就是通过JNI接口(它还常用于java与操作系统、硬件交互),找到class文件后并装载进JVM,然后找到main方法,最后执行。
JVM基本结构
可能通过上面的描述,大家对JVM运行流程有了一个粗略的认识,那么JVM内部到底是怎么执行一个class文件的呢,也就是上图中最后一步第6步的内部细节是怎样的呢?要了解这个问题,我们首先得看一下JVM的内部结构:

从这个结构不难看出,class文件被jvm装载以后,经过jvm的内存空间调配,最终是由执行引擎完成class文件的执行。当然这个过程还有其他角色模块的协助,这些模块协同配合才能让一个java程序成功的运行,下面就详细介绍这些模板,它们也是后面学习jvm最重要的部分。
内存空间:
JVM内存空间包含:方法区、java堆、java栈、本地方法栈。
方法区是各个线程共享的区域,存放类信息、常量、静态变量。
java堆也是线程共享的区域,我们的类的实例就放在这个区域,可以想象你的一个系统会产生很多实例,因此java堆的空间也是最大的。如果java堆空间不足了,程序会抛出OutOfMemoryError异常。
java栈是每个线程私有的区域,它的生命周期与线程相同,一个线程对应一个java栈,每执行一个方法就会往栈中压入一个元素,这个元素叫“栈帧”,而栈帧中包括了方法中的局部变量、用于存放中间状态值的操作栈,这里面有很多细节,我们以后再讲。如果java栈空间不足了,程序会抛出StackOverflowError异常,想一想什么情况下会容易产生这个错误,对,递归,递归如果深度很深,就会执行大量的方法,方法越多java栈的占用空间越大。
每个帧代表一个方法,Java方法有两种返回方式,return和抛出异常,两种方式都会导致该方法对应的帧出栈和释放内存。
帧的组成:局部变量区(包括方法参数和局部变量,对于instance方法,还要首先保存this类型,其中方法参数按照声明顺序严格放置,局部变量可以任意放置),操作数栈,帧数据区(用来帮助支持常量池的解析,正常方法返回和异常处理)。
本地方法栈角色和java栈类似,只不过它是用来表示执行本地方法的,本地方法栈存放的方法调用本地方法接口,最终调用本地方法库,实现与操作系统、硬件交互的目的。
PC寄存器,说到这里我们的类已经加载了,实例对象、方法、静态变量都去了自己改去的地方,那么问题来了,程序该怎么执行,哪个方法先执行,哪个方法后执行,这些指令执行的顺序就是PC寄存器在管,它的作用就是控制程序指令的执行顺序。
执行引擎当然就是根据PC寄存器调配的指令顺序,依次执行程序指令。
静态变量+常量+类信息+运行时常量池存在方法区中,实例变量存在堆内存中。
基本类型的变量和对象的引用变量都是在函数的栈内存中分配。
另一篇有见解的jvm 文章: https://blog.csdn.net/Luomingkui1109/article/details/72820232
浅谈JVM及原理的更多相关文章
- 浅谈JVM编译原理->.java文件转变为.class文件的过程
为什么需要编译? 我们平常写代码,有规范的命名方式,都能够看得懂,但是我们写的代码计算机是看不懂的,所以需要编译,也就是一个转换的过程,如下: 1.这个是咱们平时写的代码,就比较好理解,对人友好 2. ...
- 浅谈jvm中的垃圾回收策略
下面小编就为大家带来一篇浅谈jvm中的垃圾回收策略.小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧 java和C#中的内存的分配和释放都是由虚拟机自动管理的,此前我已 ...
- 浅谈html运行原理
浅谈HTML运行原理,所谓的HTML简单的来说就是一个网页,虽然第一节就讲html原理可能大家会听不懂,就当是给一个初步印象把,至少大概知道一个网页的运行流程是怎样的,下面上一张图: 大致的一个htm ...
- 浅谈React工作原理
浅谈React工作原理:https://www.cnblogs.com/yikuu/p/9660932.html 转自:https://cloud.tencent.com/info/63f656e0b ...
- 浅谈JVM线程调度机制及主要策略
在之前有说过线程,应该都知道,所谓线程就是进程中的一个子任务,一个进程有多个线程.今天的话主要就是谈一谈JVM线程调度机制.我们结合线程来说,当我们在做多线程的案例时,如一个经典案例,火车站卖票. * ...
- 浅谈JVM垃圾回收
JVM内存区域 要想搞懂啊垃圾回收机制,首先就要知道垃圾回收主要回收的是哪些数据,这些数据主要在哪一块区域. Java8和Java8之前的相同点有很多. 都有虚拟机栈,本地方法栈,程序计数器,这三个是 ...
- 浅谈JVM和垃圾回收
写在前面 简单的介绍一下JVM(Java Virtual Machine)吧,它也叫Java虚拟机.虽然它叫虚拟机,但是实际上不是我们所理解的虚拟机,它更像操作系统中的一个进程.JVM屏蔽了各个操作系 ...
- 浅谈JVM内存分配与垃圾回收
大家好,我是微尘,最近又去翻了周志明老师的<深入理解Java虚拟机>这本书.已经看了很多遍了,每次都感觉似乎看懂了,但没过多久就忘了.这次翻了第三章的垃圾收集器与内存分配策略,感觉有了新的 ...
- [iOS]浅谈NSRunloop工作原理和相关应用
一. 认识NSRunloop 1.1 NSRunloop与程序运行 那么具体什么是NSRunLoop呢?其实NSRunLoop的本质是一个消息机制的处理模式.让我们首先来看一下程序的入口——main ...
随机推荐
- 现代操作系统第三版高清.pdf中文版免费下载
百度云盘:链接: https://pan.baidu.com/s/1i57XmxJ 密码: rmga
- MySQL中添加、修改、删除约束
https://blog.csdn.net/dz77dz/article/details/82119000 主要包含的约束: 非空.唯一.check.not null.默认值.主键.外键
- JVM调优总结(三)——分代垃圾回收详述
为什么要分代 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的.因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率. 在Java程序运行的过程中,会产生大量的对象, ...
- 创建ThreadFactory实例的多种方式
spring的CustomizableThreadFactory guava的MoreExecutors.platformThreadFactory()静态方法 guava的ThreadFactory ...
- js怎么上传文件夹
1 背景 用户本地有一份txt或者csv文件,无论是从业务数据库导出.还是其他途径获取,当需要使用蚂蚁的大数据分析工具进行数据加工.挖掘和共创应用的时候,首先要将本地文件上传至ODPS,普通的小文件通 ...
- 记ubuntu sudo无法使用,su密码不对的解决办法
前言 因为我有强制关机的习惯, 然后就杯具了.. ubuntu版本是 16.04 sudo没法使用, su密码不对, 顿时我就慌了 解决方案 1.1.开机点击ESC,进去GUN GRUB界面 1.2. ...
- (79)【按键】[独立按键] - 1: 单击,双击,三击以及N击
此按键程序的实现的功能是单个独立按键的[单击],[长按],[双击],[三击]以及[多击].本文分为三个部分, 第一个部分是说[单击],[长按]的程序: 第二部分是讲[双击]: 第三部分是讲[三击],[ ...
- Redis高级命令及特性(安全性)
高级命令 keys * : 返回满足的所有键 ,可以模糊匹配 exists :是否存在指定的key,存在返回1,不存在返回0 exprie:设置某个key的过期时间 ttl:查看剩余时 ...
- 5.Python注释(多行注释和单行注释)用法详解
Python单行注释 Python 中使用井号(‘#’)作为单行注释的符号,语法格式为: # 注释内容 也就是说,从符号‘#’处开始,直到换行处结束,此部分内容都作为注释的内容,当程序执行时,这部分内 ...
- Redis单节点部署
安装Redis 由于REDIS使用单线程处理请求,CPU的快慢最对REDIS的性能有较大影响,官方建议INTEL的CPU,其效率能比AMD高一倍左右. 下载Redis:wget http://down ...