龙空技术网

Java类加载及赋值顺序

枫林晚粥 232

前言:

此时我们对“java类的赋值”大致比较注重,朋友们都想要学习一些“java类的赋值”的相关文章。那么小编同时在网摘上收集了一些关于“java类的赋值””的相关文章,希望各位老铁们能喜欢,同学们一起来学习一下吧!

1.类加载器可以大致划分为以下三类:

启动类加载器:Bootstrap ClassLoader,负责加载存放在JDK\jre\lib(JDK代表JDK的安装目录,下同)下,或被-Xbootclasspath参数指定的路径中的,并且能被虚拟机识别的类库(如rt.jar,所有的java.*开头的类均被Bootstrap ClassLoader加载)。启动类加载器是无法被Java程序直接引用的。

扩展类加载器:Extension ClassLoader,该加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载DK\jre\lib\ext目录中,或者由java.ext.dirs系统变量指定的路径中的所有类库(如javax.*开头的类),开发者可以直接使用扩展类加载器。

应用程序类加载器:Application ClassLoader,该类加载器由sun.misc.Launcher$AppClassLoader来实现,它负责加载用户类路径(ClassPath)所指定的类,开发者可以直接使用该类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

2.JVM类加载机制全盘负责,当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入父类委托,先让父类加载器试图加载该类,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类缓存机制,缓存机制将会保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存区寻找该Class,只有缓存区不存在,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存入缓存区。这就是为什么修改了Class后,必须重启JVM,程序的修改才会生效3.类加载有三种方式:

1、命令行启动应用时候由JVM初始化加载

2、通过Class.forName()方法动态加载

3、通过ClassLoader.loadClass()方法动态加载

Class.forName()和ClassLoader.loadClass()区别

Class.forName():将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块;ClassLoader.loadClass():只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。4.双亲委派模型

双亲委派模型的工作流程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。

双亲委派机制:

1、当AppClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成。

2、当ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成。

3、如果BootStrapClassLoader加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用ExtClassLoader来尝试加载;

4、若ExtClassLoader也加载失败,则会使用AppClassLoader来加载,如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException。

ClassLoader源码分析:

public Class loadClass(String name)throws ClassNotFoundException {        return loadClass(name, false);    }protected synchronized Class loadClass(String name, boolean resolve)throws ClassNotFoundException {// 首先判断该类型是否已经被加载        Class c = findLoadedClass(name);        if (c == null) {//如果没有被加载,就委托给父类加载或者委派给启动类加载器加载            try {                if (parent != null) {//如果存在父类加载器,就委派给父类加载器加载                    c = parent.loadClass(name, false);                } else {//如果不存在父类加载器,就检查是否是由启动类加载器加载的类,通过调用本地方法native Class findBootstrapClass(String name)                    c = findBootstrapClass0(name);                }            } catch (ClassNotFoundException e) {// 如果父类加载器和启动类加载器都不能完成加载任务,才调用自身的加载功能                c = findClass(name);            }        }        if (resolve) {            resolveClass(c);        }        return c;    }

双亲委派模型意义:

沙箱安全机制:自己写的java.lang.String.class不会被加载,防止核心API被篡改避免重复加载,保证Java程序安全稳定运行

Tomcat底层类加载器使用的非双亲委派机制

5. Java中赋值顺序:

1. 父类的静态变量赋值

2. 自身的静态变量赋值

3. 父类成员变量赋值

4. 父类块赋值

5. 父类构造函数赋值

6. 自身成员变量赋值

7. 自身块赋值

8. 自身构造函数赋值

不考虑父类时:

(1)自身的静态变量赋值

(2)自身成员变量赋值

(3)自身块赋值

(4)自身构造函数赋值

若(1)中静态变量为自身引用,则会先执行自身构造函数

标签: #java类的赋值