JAVA类加载器实现了一部分 JRE加载JAVA CLASSES到 JVM 的功能。bootstrap
ClssLoader 实现了懒加载,而且使得JVM没必要关心加载文件以及所使用的文件系统。数组
类加载器虽然只用于实现类的加载动做,但它在JAVA程序中所起到的做用远远不限于类加载阶段。对于任意一个类,都须要有由加载它的类加载器和这个类自己一同确立其在JAVA虚拟机中的惟一性,每个类加载器,都拥有一个独立的类名称空间。这意味着惟一肯定一个JAVA的类须要确认
JavaClassloader + Java Class 相同。app
JVM启动时,这三种加载器将被启动:ui
1 Bootstrap class loaderthis
C++语言实现,是虚拟机自身一部分,其余都是JAVA实现继承java.lang.ClassLoader。负责加载code
双亲委派模型Parents Delegation Modelorm
双亲委派模型是经过Composition模式实现
对象
双亲委派模型的基本思路是,一个类加载器收到了类加载请求,本身不会加载,而是调用父类加载器去完成blog
sun.misc.Launcher中继承关系以下
ClassLoader解释以下
java.lang.ClassLoader
A class loader is an object that is responsible for loading classes. The class ClassLoader is an abstract class. Given the binary name of a class, a class loader should attempt to locate or generate data that constitutes a definition for the class. A typical strategy is to transform the name into a file name and then read a “class file” of that name from a file system.…
ClassLoader class uses a delegation model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader. When requested to find a class or resource, a ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself. The virtual machine’s built-in class loader, called the “bootstrap class loader”, does not itself have a parent but may serve as the parent of a ClassLoader instance.
Class loaders that support concurrent loading of classes are known as parallel capable class loaders and are required to register themselves at their class initialization time by invoking the registerAsParallelCapable() method. Note that the ClassLoader class is registered as parallel capable by default. However, its subclasses still need to register themselves if they are parallel capable.
In environments in which the delegation model is not strictly hierarchical, class loaders need to be parallel capable, otherwise class loading can lead to deadlocks because the loader lock is held for the duration of the class loading process (see loadClass methods).
Normally, the Java virtual machine loads classes from the local file system in a platform-dependent manner. For example, on UNIX systems, the virtual machine loads classes from the directory defined by the CLASSPATH environment variable.
However, some classes may not originate from a file; they may originate from other sources, such as the network, or they could be constructed by an application. The method defineClass converts an array of bytes into an instance of class Class. Instances of this newly defined class can be created using Class.newInstance.
基本能够总结以下:
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 } if (c == null) { // 若果父加载器依然没法加载 在调用自己findClass方法进行类加载 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; }
一个类实例化是被其余的类或方法进行调用,其实际的情况以下:
ClassLoader loader = new NetworkClassLoader(host, port); Object main = loader.loadClass("Main", true).newInstance();
类加载器在进行类加载以后,再对类进行实例化。
这时候有个疑问,咱们常常获取的类的Class到底是什么?根据源码定义
Instances of the class Class represent classes and interfaces in a running Java application. An enum is a kind of class and an annotation is a kind of interface. Every array also belongs to a class that is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions. The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects.
咱们能够知道:
一般咱们获取ClassLoader是经过获取
public ClassLoader getClassLoader() { ClassLoader cl = getClassLoader0(); if (cl == null) return null; SecurityManager sm = System.getSecurityManager(); if (sm != null) { ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass()); } return cl; }
getClassLoader0()是Jvm本地方法,其实是获取当前类加载时的加载器。Class在运行初会加载本地方法集,这部分会在Jvm中实现。Class的构造方法是私有的,只能有JVM在实例化Class的时候进行调用,所以getClassLoader0()实际就是从JVM中获取加载器相关信息。
private static native void registerNatives(); static { registerNatives(); } /* * Private constructor. Only the Java Virtual Machine creates Class objects. * This constructor is not used and prevents the default constructor being * generated. */ private Class(ClassLoader loader) { // Initialize final field for classLoader. The initialization value of non-null // prevents future JIT optimizations from assuming this final field is null. classLoader = loader; }