JVM那些事儿之执行原理(二)
来源:互联网 发布:ae 2017 cc mac破解版 编辑:程序博客网 时间:2024/06/05 23:55
JVM那些事儿之执行原理(二)
案例
当一个java程序员把第一个helloworld程序敲出来后,它是怎么在console里打印出“helloworld”的?
编写Java程序
public class HelloWorld { public static void main(String[] args) { System.out.println(“hello world!”); }}
通过javac将.java文件编译成.class字节码文件
> javac HelloWorld.java
使用 javap查看.class字节码文件
> javap -verbose HelloWorld.class
此时可以看到这样一个字符串。这个字符串就是编译后的内容
Classfile /jvmtest/HelloWorld.class Last modified 2017-8-12; size 426 bytes MD5 checksum 4efac412ef483c8a3fe7489c87d15c8c Compiled from "HelloWorld.java"public class HelloWorld minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPERConstant pool: #1 = Methodref #6.#15 // java/lang/Object."<init>":()V #2 = Fieldref #16.#17 // java/lang/System.out:Ljava/io/PrintStream; #3 = String #18 // hello world! #4 = Methodref #19.#20 // java/io/PrintStream.println:(Ljava/lang/String;)V #5 = Class #21 // HelloWorld #6 = Class #22 // java/lang/Object #7 = Utf8 <init> #8 = Utf8 ()V #9 = Utf8 Code #10 = Utf8 LineNumberTable #11 = Utf8 main #12 = Utf8 ([Ljava/lang/String;)V #13 = Utf8 SourceFile #14 = Utf8 HelloWorld.java #15 = NameAndType #7:#8 // "<init>":()V #16 = Class #23 // java/lang/System #17 = NameAndType #24:#25 // out:Ljava/io/PrintStream; #18 = Utf8 hello world! #19 = Class #26 // java/io/PrintStream #20 = NameAndType #27:#28 // println:(Ljava/lang/String;)V #21 = Utf8 HelloWorld #22 = Utf8 java/lang/Object #23 = Utf8 java/lang/System #24 = Utf8 out #25 = Utf8 Ljava/io/PrintStream; #26 = Utf8 java/io/PrintStream #27 = Utf8 println #28 = Utf8 (Ljava/lang/String;)V{ public HelloWorld(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 1: 0 public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=1, args_size=1 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3 // String hello world! 5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return LineNumberTable: line 3: 0 line 4: 8}SourceFile: "HelloWorld.java"
执行.class文件
> java HelloWorld
此时控制台会打印出
> hello world!
执行原理
如何生成.class文件咱们先不讲,反正文件是有了。咱们就来讲讲拿到这个文件后,JVM在执行这个文件时的过程。
先说明一下JVM到底是什么语言开发的?Java的解释器肯定不是Java开发了,其实,JVM主要是C/C++开发的,里面还有很多汇编语言。我们在执行.class文件时采用的方式是解释执行。
我们先说一个最精简的原理。
前面我们已经看到.class文件里面,会分成不同的方法。JVM在解释的时候,先把内存什么的规划好(具体怎么规划的后面讲),然后大概看一下有哪些方法,把这些方法都转换成机器码保存起来。当JVM自检结束后,将会先从main方法开始执行。
具体执行依赖的是C/C++的函数指针技术,这个技术让JVM可以直接执行一段机器码,而前面我们已经把Java的方法都转换成机器码保存起来了,这时候利用这个技术直接执行机器码就好了。
大家注意了,前面说的这段算是JVM最精彩的部分,为什么呢?刚开始的JVM可不是这样的,所以Java刚出来的时候,由于执行速度慢,被大家诟病,后来改了这个方案后,再加上将字节码转换成机器码的过程不断改进、优化,现在的Java程序在某些方面已经达到甚至超越了C/C++的速度。
以后再有人跟你说java速度慢,你就可以怼回去了。
体系结构
类装载子系统
负责把类从文件系统中装入内存
GC子系统
垃圾收集器的主要工作室自动回收不再运行的程序引用对象所占用的内存,此外,它还可能负责那些还在使用的对象,以减少的堆碎片。
内存区
用于存储字节码,程序运行时创建的对象,传递给方法的参数,返回值,局部变量和中间计算结果。
执行引擎
1、最简单的:一次性解释字节码。
2、快,但消耗内存的:“即时编译器”,第一次被执行的字节码会被编译成机器代码,放入缓存,以后调用可以重用。
3、自适应优化器,虚拟机开始的时候会解释字节码,但是会监视运行中程序的活动,并记录下使用最频繁的代码段。程序运行的时候,虚拟机只把使用最频繁的代码编译成本地代码,其他的代码由于使用的并不频繁,继续保留为字节码–由虚拟机继续解释他们。一般可以使java虚拟机80%~90%的时间里执行被优化过的本地代码,只需要编译10%~20%对性能优影响的代码。
4、由硬件芯片组成,他用本地方法执行java字节码,这种执行引擎实际上是内嵌在芯片里的。
- JVM那些事儿之执行原理(二)
- JVM工作原理那些事儿
- JVM那些事儿之简介(一)
- JVM那些事儿(二)——垃圾回收
- JVM那些事儿之内存空间管理(三)
- 敏捷那些事儿(二)
- Ext2那些事儿(二)
- iTween那些事儿(二)
- SQL那些事儿(二)
- JVM内存那些事儿
- 网络中的那些事儿(二)之总体规划
- Android 开发之 Gradle那些事儿(二)
- 实习的那些事儿之二
- C语言的那些事儿之二
- iOS 越狱开发那些事儿之二
- JVM那些事儿(一)——jvm内存介绍
- 读书笔记JVM探秘之六:编译器的那些事儿
- JVM工作原理之二:JVM类的装载与执行
- 2.常用控件:ListView
- ACM第三次比赛题目及标准程序(贪心)
- 《剑指offer》牛客网java题解-从尾到头打印链表
- 循环——的斐波那契数列——虽然听懂了,但直接听答案果然效果不好,忘得真快
- Effective C++学习心得一
- JVM那些事儿之执行原理(二)
- 【线段树】备用模板
- HDU 6105 Gameia (博弈)
- 十进制转八进制(递归版)
- 高效算法设计(二分查找,范围统计)
- Python:在文件中的每一行添加一个逗号
- 文章标题
- Kotlin集合及其操作函数
- Python代码实现简单的MNIST手写数字识别(适合初学者看)