龙空技术网

面试题:谈谈你对Java类加载机制的理解

java架构设计 913

前言:

此时小伙伴们对“动态加载c语言”大概比较讲究,朋友们都需要知道一些“动态加载c语言”的相关资讯。那么小编同时在网摘上收集了一些关于“动态加载c语言””的相关内容,希望同学们能喜欢,朋友们快快来了解一下吧!

类加载机制的定义

所谓的类加载机制就是虚拟机将class文件加载到内存,并对该文件进行验证、准备、解析和初始化,最终形成虚拟机可以直接使用的Java对象,即java.lang.Class。

但是JVM启动时候并不会立即加载所有的类,而是在需要的时候才去加载它。

类加载过程

类加载过程

JVM虚拟机中的类的生命周期主要有7个阶段:加载、验证、准备、解析、初始化、使用、卸载,其中类加载过程包括:加载、验证、准备、解析、初始化这5个阶段。

加载:

通过类的全限定名称获取该类文件的二进制字节流;

将这个字节流所代表的静态存储结构转换为方法区的运行时数据结构;

在java堆中生成代表这个类的java.lang.Class对象,作为对方法区这些数据结构的访问入口;

验证:

验证是为了确保加载的class文件符合Java虚拟机的规范要求,包含以下验证:

文件格式验证:是否以16进制cafebaby开头、版本号是否正确等;

元数据验证:对Java语义进行校验,检查是否存在不符合Java语法的元数据信息;例如是否有父类、是否继承了final类、一个非抽象类是否实现了所有的抽象方法;

字节码验证:进行数据流和控制流分析,确保程序的语义是合法的,符合逻辑的;对类的方法进行分析,确保类的方法是安全的;

符号引用验证:对类自身引用的外部变量是否能够匹配到,确保后面的解析动作能够正常执行;

准备:

为类的静态变量分配内存,并初始化默认值:

准备阶段各数据类型默认零值

解析:

把类中的符号引用转换为直接引用

初始化:

执行类构造器方法,给类变量进行赋值操作,前面准备过程已经给类变量做初始化默认值了,这里开始给各个静态变量按照程序代码的定义来赋值;初始化的步骤:

5.1、如果这个类还没有被加载和链接,则先执行加载和链接的动作;

5.2、如果该类的父类还没有初始化,则先初始化其父类;

5.3、如果该类中有初始化语句,则依次执行这些初始化语句;

类加载器的层次启动类加载器:

Bootstrap ClassLoader

加载$JAVA_HOME中jre/lib/rt.jar包中所有的类以及Xbootclasspath选项指定的jar包

扩展类加载器:

ExtClassLoader

加载java平台中扩展功能的一些jar包,包括jre/lib/*.jar中的所有类以及-Djava.ext.dirs指定目录下的jar包

系统类加载器:

AppClassLoader

加载classpath中指定的jar包以及-Djava.class.path所指定目录下的类和jar包

自定义类加载器:

Custom ClassLoader

通过java.lang.ClassLoader的子类自定义加载class,属于应用程序根据需要自定义的ClassLoader,例如tomcat、jboss都会根据j2ee规范自行实现ClassLoader

双亲委派机制ClassLoader中loadClass()源码

protected Class<?> loadClass(String name, boolean resolve)    throws ClassNotFoundException{    synchronized (getClassLoadingLock(name)) {        // 首先检查该类是否已经被加载过        Class<?> c = findLoadedClass(name);        if (c == null) {            long t0 = System.nanoTime();            try {                if (parent != null) {                    //如果父类加载器存在,则让父加载器加载                    c = parent.loadClass(name, false);                } else {                    //如果没有父类,则让启动类加载器加载                    c = findBootstrapClassOrNull(name);                }            } catch (ClassNotFoundException e) {                // ClassNotFoundException thrown if class not found                // from the non-null parent class loader            }            //如果还没找到父类加载器,则调用findClass方法            if (c == null) {                // If still not found, then invoke findClass in order                // to find the class.                long t1 = System.nanoTime();                c = findClass(name);                // this is the defining class loader; record the stats                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);                sun.misc.PerfCounter.getFindClasses().increment();            }        }        //如果需要解析,则解析这个类        if (resolve) {            resolveClass(c);        }        return c;    }}
如何打破双亲委派机制?自定义类加载器,重写loadClass()和findClass();java中的SPI机制;OSGi的热部署、热更新;

标签: #动态加载c语言