Java虚拟机如何运行Java字节码
一、Java的class文件的内容
1.首先编写一个简单的代码
public class StringDemo {
public static void main(String[] args) {
String s=new String("hello world");
System.out.println(s);
}
}
2.运行程序编译成class文件,class文件的查看可以用Java class文件分析工具 -- Classpy
3.这种字节码文件我们肯定看不懂,所以我们可以通过指令Javap来转换成我们人类可以看懂的

4.打开StringDemo.txt文件,即下图的内容
public class com.dada.demo.controller.StringDemo
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #8.#24 // java/lang/Object."":()V
#2 = Class #25 // java/lang/String
#3 = String #26 // hello world
#4 = Methodref #2.#27 // java/lang/String."":(Ljava/lang/String;)V
#5 = Fieldref #28.#29 // java/lang/System.out:Ljava/io/PrintStream;
#6 = Methodref #30.#31 // java/io/PrintStream.println:(Ljava/lang/String;)V
#7 = Class #32 // com/dada/demo/controller/StringDemo
#8 = Class #33 // java/lang/Object
#9 = Utf8
#10 = Utf8 ()V
#11 = Utf8 Code
#12 = Utf8 LineNumberTable
#13 = Utf8 LocalVariableTable
#14 = Utf8 this
#15 = Utf8 Lcom/dada/demo/controller/StringDemo;
#16 = Utf8 main
#17 = Utf8 ([Ljava/lang/String;)V
#18 = Utf8 args
#19 = Utf8 [Ljava/lang/String;
#20 = Utf8 s
#21 = Utf8 Ljava/lang/String;
#22 = Utf8 SourceFile
#23 = Utf8 StringDemo.java
#24 = NameAndType #9:#10 // "":()V
#25 = Utf8 java/lang/String
#26 = Utf8 hello world
#27 = NameAndType #9:#34 // "":(Ljava/lang/String;)V
#28 = Class #35 // java/lang/System
#29 = NameAndType #36:#37 // out:Ljava/io/PrintStream;
#30 = Class #38 // java/io/PrintStream
#31 = NameAndType #39:#34 // println:(Ljava/lang/String;)V
#32 = Utf8 com/dada/demo/controller/StringDemo
#33 = Utf8 java/lang/Object
#34 = Utf8 (Ljava/lang/String;)V
#35 = Utf8 java/lang/System
#36 = Utf8 out
#37 = Utf8 Ljava/io/PrintStream;
#38 = Utf8 java/io/PrintStream
#39 = Utf8 println
{
public com.dada.demo.controller.StringDemo();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
LineNumberTable:
line 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/dada/demo/controller/StringDemo;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=2, args_size=1
0: new #2 // class java/lang/String
3: dup
4: ldc #3 // String hello world
6: invokespecial #4 // Method java/lang/String."":(Ljava/lang/String;)V
9: astore_1
10: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
13: aload_1
14: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
17: return
LineNumberTable:
line 5: 0
line 6: 10
line 7: 17
LocalVariableTable:
Start Length Slot Name Signature
0 18 0 args [Ljava/lang/String;
10 8 1 s Ljava/lang/String;
}
SourceFile: "StringDemo.java"
5.上面的内容我们可以根据jvm指令码表,就知道什么意思啦
二、Java运行时数据区
1.方法区
Jvm用来存储加载类的信息、常量、静态变量、编译后的代码等数据
2.堆内存
Jvm启动时创建,存放对象的实例。垃圾回收器主要就是管理堆内存。
3.虚拟机栈
虚拟机栈,每个线程都在这个空间有一个私有的空间。线程栈由多个栈帧组成,一个线程执行一个或多个方法,一个方法对应一个栈帧。栈帧的内容包含:局部变量表、操作数栈、动态链接、方法返回地址、附加信息等。栈内存默认最大1M,超出则抛出StackOverflowError。
4.本地方法栈 无锡人流医院哪家好 http://mobile.wxbhnkyy120.com/
和虚拟机栈功能类似,虚拟机栈是为虚拟机执行JAVA方法而准备的,本地方法栈是为虚拟机使用Native本地方法而准备的。
5.程序计数器
程序计数器记录当前线程执行字节码的位置,存储的是字节码指令地址,如果执行Native方法,则计数器值为空。每个线程在这个空间有一个私有的空间,占用内存空间很少。CPU同一时间,只会执行一条线程中的指令。JVM多线程会轮流切换并分配CPU执行时间的方式。为了线程切换后,需要通过程序计数器,来恢复正确的执行位置。
在了解上面的基础知识后,我们开始了解具体的执行过程。
三、Java虚拟机如何运行Java字节码?
标准JDK中的HotSpot是如何运行Java字节码的呢?(常见的虚拟机分三种1.HotSpot 2. JRockit 3.IBM的jvma)
需要从两个角度考虑:
虚拟机角度
底层硬件角度
1.1虚拟机角度
1.1.1从虚拟机角度是如何运行Java字节码的?
①首先会将Java代码编译成的class文件加载到JVM
②加载后的Java类会存放到方法区中。
③实际运行时,JVM会执行方法区内的代码。
④运行时,每当调用进入一个Java方法,JVM会在当前线程的Java方法栈中生成一个栈帧。
⑤退出执行的Java方法时,无论是不是正常返回,JVM都会弹出并舍弃掉当前线程的当前栈帧。
1.1.2栈帧是什么?
①用于存放局部变量、字节码的操作数
②栈帧的大小是提前计算好的。
③JVM不要求栈帧在内存空间内连续分布。
1.1.3JVM中内存组成部分有哪些?线程共享的是哪些部分?线程私有的是哪些部分?
线程共享:
①方法区:存放加载后的Java类
②堆:创建的对象实例
线程私有:
①Java方法栈: 面向Java方法
②本地方法栈: 面向C++写的native方法
③PC寄存器: 存放各个线程执行位置。
2.1硬件角度
2.1.1从硬件角度角度是如何运行Java字节码的?
①Java字节码无法直接执行
②JVM需要将字节码翻译成机器码
2.1.2JVM(如HotSpot)如何将字节码翻译成机器码?
两种方法:
①解释执行-逐条将字节码翻译成机器码执行
②即时编译(Just-In-Time compilation, JIT)-将一个方法中的字节码都编译成机器码后再执行。
总结:
Hello.java-->被编译成Hello.class,然后被加载到jvm的虚拟机里,存放到方法区内。实际运行代码时执行方法区的代码,每当调用进入一个Java方法,JVM会在当前线程的Java方法栈中生成一个栈帧,在栈帧内操作数栈根据指令码的顺序操作本地变量表来实现代码的执行,退出执行的Java方法时,无论是不是正常返回,JVM都会弹出并舍弃掉当前线程的当前栈帧。
Java虚拟机如何运行Java字节码的更多相关文章
- 深入理解Java虚拟机06--虚拟机字节码执行引擎
一.前言 物理机的执行引擎是直接在物理硬件如CPU.操作系统.指令集上运行的,但是对于虚拟机来讲,他的执行引擎由自己实现. 执行引擎有统一的外观(Java虚拟机规范),不同类型的虚拟机都遵循了这一规范 ...
- 深入理解java虚拟机(六)字节码指令简介
Java虚拟机指令是由(占用一个字节长度.代表某种特定操作含义的数字)操作码Opcode,以及跟随在其后的零至多个代表此操作所需参数的称为操作数 Operands 构成的.由于Java虚拟机是面向操作 ...
- 深入理解java虚拟机(5)---字节码执行引擎
字节码是什么东西? 以下是百度的解释: 字节码(Byte-code)是一种包含执行程序.由一序列 op 代码/数据对组成的二进制文件.字节码是一种中间码,它比机器码更抽象. 它经常被看作是包含一个执行 ...
- 深入解析java虚拟机-jvm运行机制
转自oschina 一:JVM基础概念 JVM(Java虚拟机)一种用于计算设备的规范,可用不同的方式(软件或硬件)加以实现.编译虚拟机的指令集与编译微处理器的指令集非常类似.Java虚拟机包括一套字 ...
- <<深入Java虚拟机>>-第二章-Java内存区域-学习笔记
Java运行时内存区域 Java虚拟机在运行Java程序的时候会将它所管理的内存区域划分为多个不同的区域.每个区域都有自己的用途,创建以及销毁的时间.有的随着虚拟机的启动而存在,有的则是依赖用户线程来 ...
- Java虚拟机及运行时数据区
1.Java虚拟机的定义 Java虚拟机(Java Virtual Machine),简称JVM.当我们说起Java虚拟机时,可能指的是如下三种不同的东西: 抽象的虚拟机规范 规范的具体实现 一个运行 ...
- JVM学习001通过实例总结Java虚拟机的运行机制
JVM学习(1)——通过实例总结Java虚拟机的运行机制-转载http://www.cnblogs.com/kubixuesheng/p/5199200.html 文章转载自:http://www.c ...
- Java虚拟机一 运行时数据区(栈、堆、方法区等)
Java虚拟机的内存管理主要分两点:内存分配以及内存回收.· 一.内存分配图: 注: 所占区域的大小与实际的内存大小比例并无直接关系. 解读: 1.如图,分成两种颜色的内存区域,其中蓝色的是线程隔离的 ...
- Java虚拟机_运行时数据区
Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域. 这些区域都有各自的用途.各自的创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程启动 ...
随机推荐
- ES6 - 对象扩展(增强字面量)
/** * 对象的扩展 * * 增强对象字面量 * * 解决问题:缩减代码 */ { /** * 1.属性简表示法 * 变量foo直接写在大括号里面.这时,属性名就是变量名, 属性值就是变量值 */ ...
- 案例:执行 JavaScript 语句
隐藏百度图片 # coding=utf-8 from selenium import webdriver driver = webdriver.PhantomJS(executable_path=r' ...
- django web问题
django生命周期 1. 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端 请求头和请求体中会包含浏览器的动作(action),这个动作通常为get或者post,体现在url之中. ...
- Python - Django - 中间件 process_template_response
process_template_response(self, request, response) 有两个参数,response 是 TemplateResponse 对象(由视图函数或者中间件产生 ...
- [ ceph ] CEPH 部署完整版(CentOS 7 + luminous)
1. 前言 拜读了 胖哥的(el7+jewel)完整部署 受益匪浅,目前 CEPH 已经更新到 M 版本,配置方面或多或少都有了变动,本博文就做一个 ceph luminous 版本完整的配置安装. ...
- tcp端口扫描与syn扫描
连接网络设备时,一般都会在网络设备端选取0-65535之间的一个端口进行连接,端口扫描是指:检查网络设备上0-65535号端口哪些端口是开启状态.如果黑客扫描到某网络设备的80端口是开启状态,那么很有 ...
- pidstat 命令详解
pidstat 概述 pidstat是sysstat工具的一个命令,用于监控全部或指定进程的cpu.内存.线程.设备IO等系统资源的占用情况.pidstat首次运行时显示自系统启动开始的各项统计信息, ...
- 【Docker学习之七】Docker图形化管理和监控
环境 docker-ce-19.03.1-3.el7.x86_64 centos 7 一.Docker管理工具 (官方三剑客)1.Docker Machine(学习的Openstack Heat)Cr ...
- spark 提交任务报错 Yarn application has already ended! It might have been killed or unable to launch application master
1.任务是提交在yarn上的,查看 resourceManager页面 有如下信息 Current usage: 58.4 MB of 1 GB physical memory used; 2.2 G ...
- C#中各种Lock的速度比较
简单写了个小程序,比较了一下C#中各种Lock的速度(前提是都没有进入wait状态). 各进入离开Lock 1kw次,结果如下: Lock Time (ms) No lock 58 CriticalS ...