一次编译,到处运行

java一直宣传的口号是:一次编译,到处运行。那么它如何实现的呢?我们看下图:

graph TD
java原程序--javac编译-->java字节码
java字节码-->jvm虚拟机
jvm虚拟机--java解释-->windows机器码
jvm虚拟机--java解释-->linux机器码
windows机器码-->windows执行
linux机器码-->linux执行

java程序经过一次编译之后,将java代码编译为字节码也就是class文件,然后在不同的操作系统上依靠不同的java虚拟机进行解释,最后再转换为不同平台的机器码,最终得到执行。这样我们是不是可以推演,如果要在mac系统上运行,是不是只需要安装mac java虚拟机就行了。那么了解了这个基本原理后,我们来看一下,一段程序是如何执行的。

public class HelloWorld {
public static void main(String[] args) {
System.out.print("Hello world");
}
}

这段程序从编译到运行,所经历的过程如下:

graph TD
java源代码--class文件-->java字节码
java字节码--加载jvm.cfg文件-->加载配置
加载配置--根据jvm.cfg的配置-->加载jvm.dll文件
加载jvm.dll文件-->初始化jvm
初始化jvm-->获取JNI接口
获取JNI接口--JNI为本地方法他可以直接与操作系统交互-->操作Class文件
操作Class文件-->找到main文件执行

jvm基本结构

可能通过上面的描述,大家对JVM运行流程有了一个粗略的认识,那么JVM内部到底是怎么执行一个class文件的呢?

graph TD
Class文件-->类加载器
类加载器-->内存空间
内存空间--运行时常量池-->方法区
方法区-->垃圾回收GC
内存空间--对象存储-->java堆
java堆-->垃圾回收GC
内存空间--局部变量表_栈帧_操作数-->java栈
java栈--线程结束自动释放-->线程私有
内存空间--本地方法库_C语言-->本地方法栈
本地方法栈-->线程私有
内存空间--JNI直接操作-->堆外内存

jvm内存分类介绍

JVM内存空间包含:方法区、java堆、java栈、本地方法栈。

  1. 方法区是各个线程共享的区域,存放类信息、常量、静态变量。

  2. java堆也是线程共享的区域,我们的类的实例就放在这个区域,可以想象你的一个系统会产生很多实例,因此java堆的空间也是最大的。如果java堆空间不足了,程序会抛出OutOfMemoryError异常。

  3. java栈是每个线程私有的区域,它的生命周期与线程相同,一个线程对应一个java栈,每执行一个方法就会往栈中压入一个元素,这个元素叫“栈帧”,而栈帧中包括了方法中的局部变量、用于存放中间状态值的操作栈,如果java栈空间不足了,程序会抛出StackOverflowError异常.

每个帧代表一个方法,Java方法有两种返回方式,return和抛出异常,两种方式都会导致该方法对应的帧出栈和释放内存。

  1. 本地方法栈角色和java栈类似,只不过它是用来表示执行本地方法的,本地方法栈存放的方法调用本地方法接口,最终调用本地方法库,实现与操作系统、硬件交互的目的。

  2. PC寄存器(程序计数器),说到这里我们的类已经加载了,实例对象、方法、静态变量都去了自己改去的地方,那么问题来了,程序该怎么执行,哪个方法先执行,哪个方法后执行,这些指令执行的顺序就是PC寄存器在管,它的作用就是控制程序指令的执行顺序。

执行引擎当然就是根据PC寄存器调配的指令顺序,依次执行程序指令。

  • 静态变量+常量+类信息+运行时常量池存在方法区中,实例变量存在堆内存中。
  • 基本类型的变量和对象的引用变量都是在函数的栈内存中分

jvm原理和代码运行的过程的更多相关文章

  1. Java程序员必了解的JVM原理以及虚拟机的运行过程

    JVM概念 虚拟机:指以软件的方式模拟具有完整硬件,VM概念 虚拟机:指以软件的方式模拟具有完整硬件系统功能.运行在一个完全隔离环境中的完整计算机系统 ,是物理机的软件实现.常用的虚拟机有VMWare ...

  2. JVM原理(Java代码编译和执行的整个过程+JVM内存管理及垃圾回收机制)

    转载注明出处: http://blog.csdn.net/cutesource/article/details/5904501 JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.e ...

  3. Tensorflow版Faster RCNN源码解析(TFFRCNN) (3)推断(测试)过程使用RPN时代码运行流程

    本blog为github上CharlesShang/TFFRCNN版源码解析系列代码笔记第三篇   推断(测试)过程不使用RPN时代码运行流程 作者:Jiang Wu  原文见:https://hom ...

  4. erlang虚拟机代码运行原理

    erlang是开源的,非常多人都研究过源码.可是.从erlang代码到c代码.这是个不小的跨度.并且代码也比較复杂. 所以这里,我利用一些时间,整理下erlang代码的运行过程.从erlang代码编译 ...

  5. Tensorflow版Faster RCNN源码解析(TFFRCNN) (2)推断(测试)过程不使用RPN时代码运行流程

    本blog为github上CharlesShang/TFFRCNN版源码解析系列代码笔记第二篇   推断(测试)过程不使用RPN时代码运行流程 作者:Jiang Wu  原文见:https://hom ...

  6. JVM生命周期与运行过程

    1. Java虚拟机的生命周期 Java虚拟机的生命周期 一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序.程序开始执行时他才运行,程序结束时他就停止.你在同一台机器上运行三个程序,就会 ...

  7. JVM原理和优化

    JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.exe来完成,通过下面4步来完成JVM环境. 1.创建JVM装载环境和配置 2.装载JVM.dll 3.初始化JVM.dll并挂界 ...

  8. jvm 原理和优化

    在csdn 上看到的,觉得很好,收藏了: 原博文地址: 濤子 http://blog.csdn.net/ning109314/article/details/10411495/ JVM工作原理和特点主 ...

  9. JVM原理

    Java语言写的源程序通过Java编译器,编译成与平台无关的‘字节码程序’(.class文件,也就是0,1二进制程序),然后在OS之上的Java解释器中解释执行,而JVM是java的核心和基础,在ja ...

随机推荐

  1. Cisco路由器基本使用

    作者:小啊博 QQ:762641008 转载请声明URL:https://www.cnblogs.com/-bobo/ 一.路由器命令行使用 router>                    ...

  2. Python控制函数运行时间

    在某个Flask项目在做后端接口时需要设置超时响应,因为接口中使用爬虫请求了多个网站,响应时间时长时短. 我需要设置一个最大响应时间,时间内如果接口爬虫没跑完,直接返回请求超时. 从网上了解到有两种方 ...

  3. Django之使用redis缓存session,历史浏览记录,首页数据实现性能优化

    Redis缓存session 配置Django缓存数据到redis中 # diango的缓存配置 CACHES = { "default": { "BACKEND&quo ...

  4. php 正则判断是否是手机号码 最新

    php 正则判断是否是手机号码 最新 标签: php正则 2013-09-22 14:31 55076人阅读 评论(1) 收藏 举报  分类: php(42)  版权声明:本文为博主原创文章,若转载请 ...

  5. SpringBoot 整合 MyBatis-Plus 入门体验

    一.前言 本文小编将基于 SpringBoot 整合 MyBatis-Plus , MyBatis-Plus 是一个 MyBatis 的增强工具,在 MyBatis 的基础上做增强并且不改变原本功能 ...

  6. 面试|简单描述MySQL中,索引,主键,唯一索引,联合索引 的区别,对数据库的性能有什么影响(从读写两方面)

    索引是一种特殊的文件(InnoDB 数据表上的索引是表空间的一个组成部分),它们 包含着对数据表里所有记录的引用指针. 普通索引(由关键字 KEY 或 INDEX 定义的索引)的唯一任务是加快对数据的 ...

  7. Node.js入门教程 第五篇 (Express框架)

    Express框架 Express是适用于Node.js web的框架,提供了大量实用功能,例如路由功能及http功能. Express 框架核心特性: 可以设置中间件来响应 HTTP 请求. 定义了 ...

  8. 2.linux系统基础笔记(延时操作、实时系统中的定时器、事件)

    延时操作 延时操作是操作系统中经常遇到的一种情形.延时的原因很多,有的时候是为了等待外设芯片处理结束,有的时候是为了暂时释放cpu的使用权,有的就是为了希望在一段时间获取资源,如果没法在单位时间内获取 ...

  9. 编程杂谈——使用emplace_back取代push_back

    近日在YouTube视频上看到关于vector中emplace_back与push_back区别的介绍,深感自己在现代C++中还是有不少遗漏的知识点,遂写了段代码,尝试比较两者的差别. 示例代码 #i ...

  10. 各种常见文件的hex文件头

    我们在做ctf时,经常需要辨认各种文件头,跟大家分享一下一些常见的文件头.   扩展名 文件头标识(HEX) 文件描述 123 00 00 1A 00 05 10 04 Lotus 1-2-3 spr ...