花卉市场网站建设基本步骤,萝卜建站,国内做性视频网站有哪些,网站地图分析工具2019独角兽企业重金招聘Python工程师标准 JAVA为我们提供了两种动态加载机制。 第一种是隐式机制。其实new一个对象和调用类的静态方法时#xff0c;就是隐式机制在工作。 第二种是显示机制。显示的机制又有两种策略 第一种是用public static Class? … 2019独角兽企业重金招聘Python工程师标准 JAVA为我们提供了两种动态加载机制。 第一种是隐式机制。其实new一个对象和调用类的静态方法时就是隐式机制在工作。 第二种是显示机制。显示的机制又有两种策略 第一种是用public static Class? forName(String className)。public static Class? forName(String name, boolean initialize, ClassLoader loader)第二种是用java.lang.ClassLoader的loadClass())。 Java程序启动时并不是一次把所有的类全部加载后再运行它总是先把保证程序运行的基础类一次性加载到jvm中其它类等到jvm用到的时候再加载。 其中类加载过程 1、寻找 jre 目录寻找jvm.dll并初始化JVM 2、产生一个Bootstrap Loader启动类加载器用C实现在java虚拟机启动的时候会利用这个类加载器来加载 JDK安装目录下的 /JRE/LIB/rt.jar等文件。 通过System.getProperty(sun.boot.class.path)可以查询。 3、Bootstrap Loader自动加载Extended Loader标准扩展类加载器 ,用java实现并将其父Loader设为Bootstrap Loader。这个ClassLoader是用来加载java的扩展API的加载JDK安装目录下的/JRE/LIB/ext目录中的类。可以通过System.getProperty(java.ext.dirs)进行查询。 也可以指定搜索路径: java -Djava.ext.dirsd:/projects/testproj/classes HelloWorld 4、Bootstrap Loader自动加载AppClass Loader系统类加载器 用java实现并将其父Loader设为Extended Loader。这个ClassLoader是用来加载用户机器上CLASSPATH设置目录中的Class的。通过System.getProperty(java.class.path)可以查询。也可以覆盖环境变量: java -cp ./lavasoft/classes HelloWorld 5、最后由AppClass Loader加载HelloWorld类。 以上就是类加载的最一般的过程。 ExtClassLoader和AppClassLoader在JVM启动后会在JVM中保存一份并且在程序运行中无法改变其搜索路径。如果想在运行时从其他搜索路径加载类就要产生新的类加载器。 在JAVA中一个类用其完全匹配类名(fully qualified class name)作为标识这里指的完全匹配类名是包名和类名。不过在JVM中一个类是用其全名再附加上一个加载类ClassLoader的实例作为唯一标识。 同一个ClassLoader加载的类文件只有一个Class实例。 但是如果同一个类文件被不同的ClassLoader载入则会有两份不同的ClassLoader实例前提是着两个类加载器不能用相同的父类加载器 双亲委托模式在任何一个自定义ClassLoader加载一个类之前它都会先委托它的父亲ClassLoader进行加载只有当父亲ClassLoader无法加载成功后才会由自己加载。 《特例是线程上下文类加载器使用线程上下文类加载器, 可以在执行线程中, 抛弃双亲委派加载链模式, 使用线程上下文里的类加载器加载类. 典型的例子有, 通过线程上下文来加载第三方库jndi实现, 而不依赖于双亲委派. 大部分java app服务器(jboss, tomcat..)也是采用contextClassLoader来处理web服务。 以 Apache Tomcat 来说每个 Web 应用都有一个对应的类加载器实例。该类加载器也使用代理模式所不同的是它是首先尝试去加载某个类如果找不到再代理给父类加载器。这与一般类加载器的顺 序是相反的。这是 Java Servlet 规范中的推荐做法其目的是使得 Web 应用自己的类的优先级高于 Web 容器提供的类。 这种代理模式的一个例外是Java 核心库的类是不在查找范围之内的。这也是为了保证 Java 核心库的类型安全。 》 在JVM加载类的时候需要经过三个步骤装载、连接、初始化。装载就是找到相应的class文件读入JVM初始化就不用说了最主要就说说连接。 forName加载的时候就会将Class进行解释和初始化。forName也有另外一个版本的方法可以设置是否初始化以及设置ClassLoader在此就不多讲了。 loadClass加载类实际上就是加载的时候并不对该类进行解释因此也不会初始化该类。 加载过程中会先检查类是否被已加载检查顺序是自底向上而加载的顺序是自顶向下也就是由上层来逐层尝试加载此类。 卸载重载一个已经加载的类是无法被更新的如果你试图用同一个ClassLoader再次加载同一个类就会得到异常java.lang.LinkageError: duplicate classdefinition我们只能够重新创建一个新的ClassLoader实例来再次加载新类。至于原来已经加载的类开发人员不必去管它因为它可能还有实例正在被使用只要相关的实例都被内存回收了那么JVM就会在适当的时候把不会再使用的类卸载。 真正完成类的加载工作是通过调用 defineClass来实现的而启动类的加载过程是通过调用 loadClass来实现的。前者称为一个类的定义加载器defining loader后者称为初始加载器initiating loader。在 Java 虚拟机判断两个类是否相同的时候使用的是类的定义加载器。 《注意事项如果A是由Bootstrap Loader所载入这个时候要加入B先交给parent进行查询这时parent为null,交给自己查询自己又没有就报错。》 线程上下文类加载器 线程上下文类加载器context class loader是从 JDK 1.2 开始引入的。类 java.lang.Thread 中的方法getContextClassLoader() 和 setContextClassLoader(ClassLoader cl) 用来获取和设置线程的上下文类加载器。如果没有通过 setContextClassLoader(ClassLoader cl) 方法进行设置的话线程将继承其父线程的上下文类加载器。Java 应用运行的初始线程的上下文类加载器是系统类加载器。在线程中运行的代码可以通过此类加载器来加载类和资源。 前面提到的类加载器的代理模式并不能解决 Java 应用开发中会遇到的类加载器的全部问题。Java 提供了很多服务提供者接口Service Provider InterfaceSPI允许第三方为这些接口提供实现。常见的 SPI 有 JDBC、JCE、JNDI、JAXP 和 JBI 等。这些 SPI 的接口由 Java 核心库来提供如 JAXP 的 SPI 接口定义包含在javax.xml.parsers 包中。这些 SPI 的实现代码很可能是作为 Java 应用所依赖的 jar 包被包含进来可以通过类路径CLASSPATH来找到如实现了 JAXP SPI 的 Apache Xerces 所包含的 jar 包。SPI 接口中的代码经常需要加载具体的实现类。如 JAXP 中的 javax.xml.parsers.DocumentBuilderFactory 类中的newInstance() 方法用来生成一个新的 DocumentBuilderFactory 的实例。这里的实例的真正的类是继承自javax.xml.parsers.DocumentBuilderFactory 由 SPI 的实现所提供的。如在 Apache Xerces 中实现的类是 org.apache.xerces.jaxp.DocumentBuilderFactoryImpl 。 而问题在于SPI 的接口是 Java 核心库的一部分是由引导类加载器来加载的SPI 实现的 Java 类一般是由系统类加载器来加载的。引导类加载器是无法找到 SPI 的实现类的因为它只加载 Java 的核心库。它也不能代理给系统类加载器因为它是系统类加载器的祖先类加载器。也就是说类加载器的代理模式无法解决这个问题。 线程上下文类加载器正好解决了这个问题。如果不做任何的设置Java 应用的线程的上下文类加载器默认就是系统上下文类加载器。在 SPI 接口的代码中使用线程上下文类加载器就可以成功的加载到 SPI 实现的类。线程上下文类加载器在很多 SPI 的实现中都会用到. 转载于:https://my.oschina.net/u/1182621/blog/146145