荐 Java类加载的整个过程

倾听梦里花落声 2月前   阅读数 22 0

Introduction

java是跨平台的编程语言。所以,它具有自己的编译器,不像其他一些语言需要一来操作系统的浏览器。

在这边文章中,我们将探讨什么是java编译器,以及它是怎么执行java程序的。java不像C语言直接可以从源文件生成一个可以执行的文件,而是将源文件转化成字节码文件(.class),字节码文件是可以被转移到其他任何安装有jre的运行环境去运行的而不会影响系统内部的结构。

java使用独立于操作系统的编译器(javac)去编译源文件得到字节码文件,然后将字节码交由JVM去执行。

编译Compilation/Compile time

在这个过程中,一个源码文件被编译器从源代码编译成字节码文件,以.class结尾。一个源代码文件对应一个.class文件。等到编译结束时,编译器会对字节码基本的语法和语义进行校验。

执行Execution/Runtime

当编译器校验完程序的错误,程序员也修改好了源文件里面相应的错误并重新编译之后。重新编译好的字节码会被加载到JVM中,加载到JVM之后,主要会经过以下三个主要步骤:

1、ClassLoader 类加载器

主程序字节码会被类加载器加载到系统的内存中去,同时,所有需要的或者被饮用的类也会被类加载器加载进内存。
类加载器。
类加载器分为两种类型:一种是原始加载器(primordial class loader ),一种是非原始加载器。
原始加载器就是系统自身自带的加载器,是加载器的加载器。原因是每个类有它的加载器,但是加载器本身也是一个类,那么它也需要一个加载器去加载它,原始加载器就是系统中用来加载类加载器的加载器。原始加载器通常是用C编写,并且不会在java的上下文中显现出来。
某些类,例如java。*包中定义的类,对于Java虚拟机和运行时系统的正确运行必不可少。它们通常被称为基类。由于历史原因,所有此类都具有一个为null的类加载器。这个空类加载器也许是原始类加载器存在的唯一标志。实际上,将空类加载器简单地视为原始类加载器更为容易。

简言之,原始加载器和非原始加载器的区别就是,原始加载器是jvm自带的,是不能被我们所修改的。那么,非原始加载器是我们可以自定义的,类的加载过程完全是我们自己掌控的。

2、Bytecode Verifier字节码校验器

这是整个编译过程中最关重要的一个步,它的作用是去检查代码是否会具有破坏性。

字节码校验器遍历字节码,构造类型状态信息,并验证所有字节码指令的参数类型。

测试的范围从简单的验证代码片段格式正确到通过简单的定理证明者传递每个代码片段以证明其遵循规则:

  • 它没有伪造指针,
  • 它没有违反访问限制,
  • 它按原样访问对象(例如,InputStream对象始终用作InputStream,而从不用作其他任何对象)。
    一种安全的语言加上生成的代码的运行时验证,可以建立一套基本的保证,保证不会违反接口。

字节码校验器充当一种看门人的角色:它确保传递给Java编译器的代码处于适合的状态,可以执行并且可以运行,而不必担心破坏Java解释器。导入的代码在通过验证者的测试之前,不允许以任何方式执行。一旦校验完成后,就会知道许多重要的属性:

  • 没有操作数栈上溢或下溢
  • 已知所有字节码指令的参数类型始终正确
  • 已知对象字段访问是合法的-私有,公共或受保护的

简言之,就是会去校验下面几个方面:

  • 一个参数变量是否被合理地初始化
  • 使用的方法会返回要求返回的适当的值
  • 运行时栈未溢出。
  • 不会违反访问权限修饰词Access specifier(modifier)(如:default,private,protected,public)
    在这里插入图片描述
    如果字节码校验器发现有任何一步出现错误,就会中止类加载的过程并且返回一个error。
    oracle 官方关于字节码校验器的说明

3、Just-in-Time Compiler JIT编译器

这是编译过程的最后一步,JIT编译器将字节码转化成机器语言,也就是0和1,然后将机器语言指令传递给本机,来帮助提高Java程序的性能。

JIT编译器默认情况下处于启用状态,并在调用Java方法时被激活。 JIT编译器将该方法的字节码编译为本地机器代码,“及时”编译以运行。编译方法后,JVM会直接调用该方法的已编译代码,而不是对其进行解释。从理论上讲,如果编译不需要处理器时间和内存使用量,则编译每种方法都可以使Java程序的速度接近本机应用程序的速度。

而JIT编译确实需要处理器时间和内存使用率。 JVM首次启动时,将调用数千种方法。即使程序最终达到了非常好的峰值性能,编译所有这些方法也会严重影响启动时间。

解释期间额外的处理器和内存使用情况意味着Java应用程序比本地应用程序执行得更慢。故JIT编译器编译好的机器码最终交交还给物理机执行,而不是由JVM执行。

JIT编译器原理的详细解释
在这里插入图片描述
以下是Oracle官方的流程图,更为准确一些。在这里插入图片描述

原创文章 53 获赞 19 访问量 2万+

注意:本文归作者所有,未经作者允许,不得转载

全部评论: 0

    我有话说: