标签:counter param 范围 span home 子类 不同的 com 上下文
类加载阶段,通过一个类的全限定名来获取描述该类的二进制流文件,实现这个动作的代码就是类加载器。
对于任意一个类,都必须由加载它的类加载器和这个类本身一起共同确立其在Java虚拟机中的唯一性。每个类加载器都有独立的类名称空间。通俗的说如果要比较两个类是否相同,必须在同一类加载器的前提下,不然没有意义。
基于JDK8及之前的版本,三个系统提供的类加载器:
图7-2中展示的各个类加载器的层次关系,被称为类加载器的双亲委派模型。双亲委派模型要求除了顶层的启动类加载器之外,其余的类加载器都要有其父类加载器。这里类加载器之间的父子关系不是通过继承来实现,通常使用组合关系来复用父类加载器的代码。
如果一个类加载器收到了类加载的请求,首先它不会自己加载该类,而是请求父类加载器去完成。每个层次的类加载器都是如此,那么所有的请求最终都会传送到顶层加载器。只有当父类加载器反应无法完成这个加载请求,子类加载器才会尝试自己去完成加载。
一个显而易见的好处就是类随着类加载器一起具备了一种带有优先级的层级关系。比如一个java.lang.Object类,无论哪个类要加载它,最终都会委派给顶层的类加载器,因此Object在各个类加载器中都是同一个类。反之如果没有使用双亲委派模型,用户自己定义一个java.lang.Object类,那么系统中会出现多个不同的Object类,应用程序会变得一片混乱。
/** * Loads the class with the specified <a href="#name">binary name</a>. The * default implementation of this method searches for classes in the * following order: * * <ol> * * <li><p> Invoke {@link #findLoadedClass(String)} to check if the class * has already been loaded. </p></li> * * <li><p> Invoke the {@link #loadClass(String) <tt>loadClass</tt>} method * on the parent class loader. If the parent is <tt>null</tt> the class * loader built-in to the virtual machine is used, instead. </p></li> * * <li><p> Invoke the {@link #findClass(String)} method to find the * class. </p></li> * * </ol> * * <p> If the class was found using the above steps, and the * <tt>resolve</tt> flag is true, this method will then invoke the {@link * #resolveClass(Class)} method on the resulting <tt>Class</tt> object. * * <p> Subclasses of <tt>ClassLoader</tt> are encouraged to override {@link * #findClass(String)}, rather than this method. </p> * * <p> Unless overridden, this method synchronizes on the result of * {@link #getClassLoadingLock <tt>getClassLoadingLock</tt>} method * during the entire class loading process. * * @param name * The <a href="#name">binary name</a> of the class * * @param resolve * If <tt>true</tt> then resolve the class * * @return The resulting <tt>Class</tt> object * * @throws ClassNotFoundException * If the class could not be found */ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded 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) { // 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方法,所父类加载器为空,则使用默认的启动类加载器加载。假如父类加载器加载失败,抛出ClassNotFoundException,调用自己的findClass()方法进行加载。
典型的两种方法: 1、使用线程上下文类加载器 2、自定义类加载器,重写loadClass方法
标签:counter param 范围 span home 子类 不同的 com 上下文
原文地址:https://www.cnblogs.com/TripL/p/13351541.html