编译原理的一些小知识

时间:2022-01-02 16:24:59

最近在看open rasp,看源码的时候涉及到一些编译原理的知识,花了半天时间了解了一下。

    JVM最主要的功能就是为了让java程序在任意平台上运行,也就是java语言的最重要的特性:平台无关性。  

Java代码编译和执行的过程:(javac命令用于编译java文件成为class文件,java命令用于执行class文件)
    1.javac是一种编译器,通常编译器都是将便于人理解的语言规范转化成机器容易理解的语言规范,而javac的任务就是
将Java源代码语言转化为JVM能够识别的一种语言(也就是.class文件,jvm字节码)
    2.Java字节码的执行是由JVM执行引擎来完成的

Java代码编译和执行的整个过程中包含有三个重要的机制:
    1.Java源代码编译机制
    2.类加载机制
    3.类执行机制

介绍下类加载机制:(https://blog.csdn.net/briblue/article/details/54973413)
    JVM的类加载是通过ClassLoader及其子类来完成的,三个自带的类加载器以及自定义加载器。
    1.Bootstrap ClassLoader:最顶层的加载器,主要用于加载核心类库,%JRE_HOME%\lib下的rt.jar、resources.jar、charsets.jar和class
等。Bootstrap ClassLoader由C++编写,本身属于JVM中的一部分,并不是一个java类,在java代码中无法获取它的引用。
    2.Extention ClassLoader:用于加载扩展的类加载器,目录%JRE_HOME%\lib\ext目录下的jar包和class文件。
    3.App ClassLoader:也称为SystemAppClass 加载当前应用的classpath的所有类。 当一个加载器没有指定父加载器时,默认的父加载器
是App ClassLoader(这里主要指的是自定义加载器如果没有设置父加载器的情况)
    4.Custom ClassLoader:自定义的类加载器,通过继承ClassLoader类并指定目录来加载目录下的class文件。

 

编译原理的一些小知识


    每个类加载器都有一个父加载器,(父加载器和父类不同,是在构造函数中通过parent属性来指定的,没有指定时为App ClassLoader)。
    双亲委托:委托机制。如果当前的类加载器没有查询到这个class对象已经加载就请求父加载器(不一定是父类)进行操作,然后以此类推。
直到Bootstrap ClassLoader。如果Bootstrap ClassLoader也没有加载过此class实例,那么它就会从它指定的路径中去查找,如果查找成功
则返回,如果没有查找成功则交给子类加载器,也就是ExtClassLoader,这样类似操作直到终点。

    一个ClassLoader中有如下几个重要函数:loadClass()、findLoadedClass()、findClass()、defineClass()。
    loadClass()通过指定的全限定类名加载class文件,一般实现该函数的步骤是(以Custom ClassLoader为例):
1.执行findLoadedClass(String)去检测整个class是否已经加载过(当前Custom ClassLoader是否已经加载过了),如果没有加载过则执行父
加载器(App ClassLoader)的loadClass()方法,该方法的具体步骤如此这般。如果父加载器为空,则用jvm中的内置的加载器去代替(也就是
Bootstrap ClassLoader)
2.如果向上委托父加载器没有加载成功,则调用findClass(String)查找。findClass()方法中又调用了defineClass()。
    defineClass():这个方法在编写自定义classloader的时候非常重要,它能将class二进制内容转换成Class对象,如果不符合要求的会抛出各种异常。

    自定义类加载器:通常一个自定义类加载器不需要修改loadClass()方法,自需要重写findClass()方法即可。自定义步骤:
    1.编写一个类继承自ClassLoader抽象类。
    2.复写它的findClass()方法。
    3.在findClass()方法中调用defineClass()。