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程序的过程中会把它所管理的内存划分为若干个不同的数据区域. 这些区域都有各自的用途.各自的创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程启动 ...
随机推荐
- tp的ajaxReturn后, 还要用echo $rt吗?
首先你要看 ajaxReturn的原型: protected function ajaxReturn ($data, $type='', $json_option=0){ ........ switc ...
- hue创建的hdfs数据在hdfs无法删除的问题。
在linux时删除时出现: rmr: Permission denied: user=root, access=ALL, inode="/user/root/.Trash/191128080 ...
- 【转】PostgreSQL与MySQL比较
转自:https://www.cnblogs.com/geekmao/p/8541817.html PostgreSQL与MySQL比较 特性 MySQL PostgreSQL 实例 通过执行 M ...
- 多线程--同步--方法块和同步块synchronized
package com.sxt.syn; /** * 线程安全: 在并发时保证数据的正确性.效率尽可能高 * synchronized * 1.同步方法 * 2.同步块 * * */ public c ...
- 使用JSP的fmt标签实现国际化支持 - smart-framework ; smart-plugin-i18n
使用JSP的fmt标签实现国际化支持 Smart-framework框架使用smart-plugin-i18n插件来完成国际化处理,原理相同,使用过滤器进行参数设置. ============== ...
- leetcode 968. Binary Tree Cameras
968. Binary Tree Cameras 思路:如果子节点只能覆盖到父节点.当前节点,但是父节点可以覆盖到他的父节点.子节点.当前节点,所以从叶子节点往上考虑 0代表子节点没有被覆盖 1代表子 ...
- centos7.6使用 supervisor 对filebeat7.3.1进程进行管理
centos7.6使用 supervisor 对filebeat7.3.1进程进行管理 Supervisor 是一个 Python 开发的 client/server 系统,可以管理和监控类 UNIX ...
- New & make in go_Code
概述 Go 语言中的 new 和 make 一直是新手比较容易混淆的东西,咋一看很相似.不过解释两者之间的不同也非常容易. 他们所做的事情,和应用的类型也不相同. 二者都是用来分配空间. new 函数 ...
- libmodbus学习笔记
libmodbus功能: a fast and portable Modbus library 库下载地址https://libmodbus.org 使用指南1)包含头文件#include <m ...
- java 欢迎页 主页 设置为servlet的方法
[参考]Java Web 设置默认首页 [参考]设置servlet或action作为欢迎页面 1. 使用HTML<meta>标签跳转至servlet <META HTTP-EQUI ...