JavaClassLoader源码分析(中)

2024-05-16 09:08
文章标签 java 分析 源码 classloader

本文主要是介绍JavaClassLoader源码分析(中),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ClassLoader与其他类的关系.png

ClassLoader的属性

说明:ClassLoader的属性与其内部类是穿插着创建的,这里写在一起了

private static native void registerNatives();//将ClassLoader类中所有native修饰的方法与C  语言描述的方法对应上相当于做了一次映射//也侧面反映了一次编写可以处处运行的一种道理,同时相当于基于java与其他语言做了一个适配static {registerNatives();}// The parent class loader for delegation// Note: VM hardcoded the offset of this field, thus all new fields// must be added *after* it.// 这个属性被JVM硬编码到类的第一个位置,标识委托的父类加载器// 这么做的原因可能是为了方便初始化ClassLoader对象的时候先初始化自己,然后自己再初始化自己拥有的属性,保障加载顺序private final ClassLoader parent;/*** Encapsulates the set of parallel capable loader types.*///这个内部类提供了并行加载类的特性private static class ParallelLoaders {private ParallelLoaders() {}// the set of parallel capable loader typesprivate static final Set<Class<? extends ClassLoader>> loaderTypes =Collections.newSetFromMap(new WeakHashMap<Class<? extends ClassLoader>, Boolean>());static {synchronized (loaderTypes) { loaderTypes.add(ClassLoader.class); }}/*** Registers the given class loader type as parallel capabale.* Returns {@code true} is successfully registered; {@code false} if* loader's super class is not registered.*/static boolean register(Class<? extends ClassLoader> c) {synchronized (loaderTypes) {if (loaderTypes.contains(c.getSuperclass())) {// register the class loader as parallel capable// if and only if all of its super classes are.// Note: given current classloading sequence, if// the immediate super class is parallel capable,// all the super classes higher up must be too.loaderTypes.add(c);return true;} else {return false;}}}/*** Returns {@code true} if the given class loader type is* registered as parallel capable.*/static boolean isRegistered(Class<? extends ClassLoader> c) {synchronized (loaderTypes) {return loaderTypes.contains(c);}}}// Maps class name to the corresponding lock object when the current// class loader is parallel capable.// Note: VM also uses this field to decide if the current class loader// is parallel capable and the appropriate lock object for class loading.//并行加载的时候为了保障不会重复加载使用下面的属性标识加载指定类的时候进行//锁定private final ConcurrentHashMap<String, Object> parallelLockMap;//这个属性跟TSL有关,也跟JDK版本有关private final Map <String, Certificate[]> package2certs;// Shared among all packages with unsigned classes// 所有的类都有指定的证书private static final Certificate[] nocerts = new Certificate[0];// The classes loaded by this class loader. The only purpose of this table// is to keep the classes from being GC'ed until the loader is GC'ed.////当前类加载加载的类向量集合,如果类加载器被回收的话这里面的类也会被回收private final Vector<Class<?>> classes = new Vector<>();// The "default" domain. Set as the default ProtectionDomain on newly// created classes.// 默认的类的访问级别private final ProtectionDomain defaultDomain =new ProtectionDomain(new CodeSource(null, (Certificate[]) null),null, this, null);// The initiating protection domains for all classes loaded by this loader//访问级别集合private final Set<ProtectionDomain> domains;// Invoked by the VM to record every loaded class with this loader.//这里没有被显示调用void addClass(Class c) {classes.addElement(c);}// The packages defined in this class loader.  Each package name is mapped// to its corresponding Package object.// @GuardedBy("itself")// 这里其实对java类中的包结构做了一次抽象,封装了Package对象,这个对象也是被类加载器所加载的,private final HashMap<String, Package> packages = new HashMap<>();// The class loader for the system// @GuardedBy("ClassLoader.class")//这里定义这个属性作为系统类加载器private static ClassLoader scl;// Set to true once the system class loader has been set// @GuardedBy("ClassLoader.class")//当系统类加载器初始化之后设置初始化状态private static boolean sclSet;// All native library names we've loaded.//已经加载的本地lib列表private static Vector<String> loadedLibraryNames = new Vector<>();// Native libraries belonging to system classes.// 本地加载lib列表 属于系统类的private static Vector<NativeLibrary> systemNativeLibraries= new Vector<>();// Native libraries associated with the class loader.//与当前类加载器相关的本地libprivate Vector<NativeLibrary> nativeLibraries = new Vector<>();// native libraries being loaded/unloaded.//已经加载或者没加载的本地libprivate static Stack<NativeLibrary> nativeLibraryContext = new Stack<>();// The paths searched for libraries//搜索的lib目录private static String usr_paths[];private static String sys_paths[];// -- Assertion management --//定义一个对象作为断言锁,后续会讲到final Object assertionLock;// The default toggle for assertion checking.// @GuardedBy("assertionLock")//默认断言状态private boolean defaultAssertionStatus = false;// Maps String packageName to Boolean package default assertion status Note// that the default package is placed under a null map key.  If this field// is null then we are delegating assertion status queries to the VM, i.e.,// none of this ClassLoader's assertion status modification methods have// been invoked.// @GuardedBy("assertionLock")//加载包的时候进行断言加锁private Map<String, Boolean> packageAssertionStatus = null;// Maps String fullyQualifiedClassName to Boolean assertionStatus If this// field is null then we are delegating assertion status queries to the VM,// i.e., none of this ClassLoader's assertion status modification methods// have been invoked.// @GuardedBy("assertionLock")//加载包的时候进行断言加锁,相当于验证是否加载了包,Map<String, Boolean> classAssertionStatus = null;

ClassLoader的构造方法

    private ClassLoader(Void unused, ClassLoader parent) {this.parent = parent;//如果当前类加载器已经注册到并行类加载器容器中就初始化对应的属性//使用并发安全容器类if (ParallelLoaders.isRegistered(this.getClass())) {parallelLockMap = new ConcurrentHashMap<>();package2certs = new ConcurrentHashMap<>();domains =Collections.synchronizedSet(new HashSet<ProtectionDomain>());assertionLock = new Object();} else {// no finer-grained lock; lock on the classloader instance//使用普通容器集合parallelLockMap = null;package2certs = new Hashtable<>();domains = new HashSet<>();assertionLock = this;}//这里的构造方法主要操作有两个//1.设置当前类加载的父类加载器//2.根据是否注册了并行类加载容器初始化对应的容器}/*** Creates a new class loader using the specified parent class loader for* delegation.** <p> If there is a security manager, its {@link* SecurityManager#checkCreateClassLoader()* <tt>checkCreateClassLoader</tt>} method is invoked.  This may result in* a security exception.  </p>** @param  parent*         The parent class loader** @throws  SecurityException*          If a security manager exists and its*          <tt>checkCreateClassLoader</tt> method doesn't allow creation*          of a new class loader.** @since  1.2*/protected ClassLoader(ClassLoader parent) {this(checkCreateClassLoader(), parent);}/*** Creates a new class loader using the <tt>ClassLoader</tt> returned by* the method {@link #getSystemClassLoader()* <tt>getSystemClassLoader()</tt>} as the parent class loader.** <p> If there is a security manager, its {@link* SecurityManager#checkCreateClassLoader()* <tt>checkCreateClassLoader</tt>} method is invoked.  This may result in* a security exception.  </p>** @throws  SecurityException*          If a security manager exists and its*          <tt>checkCreateClassLoader</tt> method doesn't allow creation*          of a new class loader.*/protected ClassLoader() {this(checkCreateClassLoader(), getSystemClassLoader());}

ClassLoader执行类加载的过程

  /*** Loads the class with the specified <a href="#name">binary name</a>.* This method searches for classes in the same manner as the {@link* #loadClass(String, boolean)} method.  It is invoked by the Java virtual* machine to resolve class references.  Invoking this method is equivalent* to invoking {@link #loadClass(String, boolean) <tt>loadClass(name,* false)</tt>}.  </p>** @param  name*         The <a href="#name">binary name</a> of the class** @return  The resulting <tt>Class</tt> object** @throws  ClassNotFoundException*          If the class was not found*///定义一个重载方法,这里的加载其实也就是创建Class实例的意思public Class<?> loadClass(String name) throws ClassNotFoundException {return loadClass(name, false);}/*** 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:** <p><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{//先根据方法名判断是否已经有类加载器在加载这个类了,//这里有两层含义1.synchronized标明这里的代码区是有并发安全问题的//意思是不能有多个线程同时执行类加载,否则会导致出现同一个类被加载多次//2.第二层含义就是下面的方法,下面的方法是classLoader提供的并行加载机制,并行加载的时候也需要//保证同一个类不能被加载多次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();//这里如果还么有找到自己才进行类加载,也就是说双亲委派模式下没有找到类,就自己加载,自己找类//这个方法在ClassLoader中是没有实现的,所以如果父类没有找到子类必须通过这个方法找类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();}}//resolve 这里如果是true,进行类的链接(验证,准备,解析)if (resolve) {resolveClass(c);}return c;}}/*** Returns the lock object for class loading operations.* For backward compatibility, the default implementation of this method* behaves as follows. If this ClassLoader object is registered as* parallel capable, the method returns a dedicated object associated* with the specified class name. Otherwise, the method returns this* ClassLoader object. </p>** @param  className*         The name of the to-be-loaded class** @return the lock for class loading operations** @throws NullPointerException*         If registered as parallel capable and <tt>className</tt> is null** @see #loadClass(String, boolean)** @since  1.7*///这里使用并发安全容器类实现类加载过程的锁机制,保证线程安全protected Object getClassLoadingLock(String className) {Object lock = this;if (parallelLockMap != null) {Object newLock = new Object();lock = parallelLockMap.putIfAbsent(className, newLock);if (lock == null) {lock = newLock;}}return lock;}

ClassLoader查找类的过程

说明:这里查找类的过程是由JVM底层实现的,比较能看懂,不做解析

     // return null if not foundprivate native Class findBootstrapClass(String name);/*** Returns the class with the given <a href="#name">binary name</a> if this* loader has been recorded by the Java virtual machine as an initiating* loader of a class with that <a href="#name">binary name</a>.  Otherwise* <tt>null</tt> is returned.  </p>** @param  name*         The <a href="#name">binary name</a> of the class** @return  The <tt>Class</tt> object, or <tt>null</tt> if the class has*          not been loaded** @since  1.1*/protected final Class<?> findLoadedClass(String name) {if (!checkName(name))return null;return findLoadedClass0(name);}private native final Class findLoadedClass0(String name);/*** Links the specified class.  This (misleadingly named) method may be* used by a class loader to link a class.  If the class <tt>c</tt> has* already been linked, then this method simply returns. Otherwise, the* class is linked as described in the "Execution" chapter of* <cite>The Java™ Language Specification</cite>.* </p>** @param  c*         The class to link** @throws  NullPointerException*          If <tt>c</tt> is <tt>null</tt>.** @see  #defineClass(String, byte[], int, int)*/protected final void resolveClass(Class<?> c) {resolveClass0(c);}private native void resolveClass0(Class c);

ClassLoader定义包的过程

说明:定义类之前先定义包,这里的包的意思跟命名空间类似,可以搜一下java中的命名空间

/*** Defines a package by name in this <tt>ClassLoader</tt>.  This allows* class loaders to define the packages for their classes. Packages must* be created before the class is defined, and package names must be* unique within a class loader and cannot be redefined or changed once* created.  </p>** @param  name*         The package name** @param  specTitle*         The specification title** @param  specVersion*         The specification version** @param  specVendor*         The specification vendor** @param  implTitle*         The implementation title** @param  implVersion*         The implementation version** @param  implVendor*         The implementation vendor** @param  sealBase*         If not <tt>null</tt>, then this package is sealed with*         respect to the given code source {@link java.net.URL*         <tt>URL</tt>}  object.  Otherwise, the package is not sealed.** @return  The newly defined <tt>Package</tt> object** @throws  IllegalArgumentException*          If package name duplicates an existing package either in this*          class loader or one of its ancestors** @since  1.2*/protected Package definePackage(String name, String specTitle,String specVersion, String specVendor,String implTitle, String implVersion,String implVendor, URL sealBase)throws IllegalArgumentException{synchronized (packages) {Package pkg = getPackage(name);if (pkg != null) {throw new IllegalArgumentException(name);}pkg = new Package(name, specTitle, specVersion, specVendor,implTitle, implVersion, implVendor,sealBase, this);packages.put(name, pkg);return pkg;}}/*** Returns a <tt>Package</tt> that has been defined by this class loader* or any of its ancestors.  </p>** @param  name*         The package name** @return  The <tt>Package</tt> corresponding to the given name, or*          <tt>null</tt> if not found** @since  1.2*/protected Package getPackage(String name) {Package pkg;synchronized (packages) {pkg = packages.get(name);}if (pkg == null) {if (parent != null) {pkg = parent.getPackage(name);} else {pkg = Package.getSystemPackage(name);}if (pkg != null) {synchronized (packages) {Package pkg2 = packages.get(name);if (pkg2 == null) {packages.put(name, pkg);} else {pkg = pkg2;}}}}return pkg;}/*** Returns all of the <tt>Packages</tt> defined by this class loader and* its ancestors.  </p>** @return  The array of <tt>Package</tt> objects defined by this*          <tt>ClassLoader</tt>** @since  1.2*/protected Package[] getPackages() {Map<String, Package> map;synchronized (packages) {map = new HashMap<>(packages);}Package[] pkgs;if (parent != null) {pkgs = parent.getPackages();} else {pkgs = Package.getSystemPackages();}if (pkgs != null) {for (int i = 0; i < pkgs.length; i  ) {String pkgName = pkgs[i].getName();if (map.get(pkgName) == null) {map.put(pkgName, pkgs[i]);}}}return map.values().toArray(new Package[map.size()]);}

ClassLoader定义/创建类的过程

说明:这里的一些方法是类加载的一些核心内容

 /*** Converts an array of bytes into an instance of class <tt>Class</tt>.* Before the <tt>Class</tt> can be used it must be resolved.  This method* is deprecated in favor of the version that takes a <a* href="#name">binary name</a> as its first argument, and is more secure.** @param  b*         The bytes that make up the class data.  The bytes in positions*         <tt>off</tt> through <tt>off len-1</tt> should have the format*         of a valid class file as defined by*         <cite>The Java™ Virtual Machine Specification</cite>.** @param  off*         The start offset in <tt>b</tt> of the class data** @param  len*         The length of the class data** @return  The <tt>Class</tt> object that was created from the specified*          class data** @throws  ClassFormatError*          If the data did not contain a valid class** @throws  IndexOutOfBoundsException*          If either <tt>off</tt> or <tt>len</tt> is negative, or if*          <tt>off len</tt> is greater than <tt>b.length</tt>.** @throws  SecurityException*          If an attempt is made to add this class to a package that*          contains classes that were signed by a different set of*          certificates than this class, or if an attempt is made*          to define a class in a package with a fully-qualified name*          that starts with "{@code java.}".** @see  #loadClass(String, boolean)* @see  #resolveClass(Class)** @deprecated  Replaced by {@link #defineClass(String, byte[], int, int)* defineClass(String, byte[], int, int)}*///注意这里的方法就是类加载过程中链接阶段要做的事情@Deprecatedprotected final Class<?> defineClass(byte[] b, int off, int len)throws ClassFormatError{return defineClass(null, b, off, len, null);}/*** Converts an array of bytes into an instance of class <tt>Class</tt>.* Before the <tt>Class</tt> can be used it must be resolved.** <p> This method assigns a default {@link java.security.ProtectionDomain* <tt>ProtectionDomain</tt>} to the newly defined class.  The* <tt>ProtectionDomain</tt> is effectively granted the same set of* permissions returned when {@link* java.security.Policy#getPermissions(java.security.CodeSource)* <tt>Policy.getPolicy().getPermissions(new CodeSource(null, null))</tt>}* is invoked.  The default domain is created on the first invocation of* {@link #defineClass(String, byte[], int, int) <tt>defineClass</tt>},* and re-used on subsequent invocations.** <p> To assign a specific <tt>ProtectionDomain</tt> to the class, use* the {@link #defineClass(String, byte[], int, int,* java.security.ProtectionDomain) <tt>defineClass</tt>} method that takes a* <tt>ProtectionDomain</tt> as one of its arguments.  </p>** @param  name*         The expected <a href="#name">binary name</a> of the class, or*         <tt>null</tt> if not known** @param  b*         The bytes that make up the class data.  The bytes in positions*         <tt>off</tt> through <tt>off len-1</tt> should have the format*         of a valid class file as defined by*         <cite>The Java™ Virtual Machine Specification</cite>.** @param  off*         The start offset in <tt>b</tt> of the class data** @param  len*         The length of the class data** @return  The <tt>Class</tt> object that was created from the specified*          class data.** @throws  ClassFormatError*          If the data did not contain a valid class** @throws  IndexOutOfBoundsException*          If either <tt>off</tt> or <tt>len</tt> is negative, or if*          <tt>off len</tt> is greater than <tt>b.length</tt>.** @throws  SecurityException*          If an attempt is made to add this class to a package that*          contains classes that were signed by a different set of*          certificates than this class (which is unsigned), or if*          <tt>name</tt> begins with "<tt>java.</tt>".** @see  #loadClass(String, boolean)* @see  #resolveClass(Class)* @see  java.security.CodeSource* @see  java.security.SecureClassLoader** @since  1.1*/protected final Class<?> defineClass(String name, byte[] b, int off, int len)throws ClassFormatError{return defineClass(name, b, off, len, null);}/*** Converts an array of bytes into an instance of class <tt>Class</tt>,* with an optional <tt>ProtectionDomain</tt>.  If the domain is* <tt>null</tt>, then a default domain will be assigned to the class as* specified in the documentation for {@link #defineClass(String, byte[],* int, int)}.  Before the class can be used it must be resolved.** <p> The first class defined in a package determines the exact set of* certificates that all subsequent classes defined in that package must* contain.  The set of certificates for a class is obtained from the* {@link java.security.CodeSource <tt>CodeSource</tt>} within the* <tt>ProtectionDomain</tt> of the class.  Any classes added to that* package must contain the same set of certificates or a* <tt>SecurityException</tt> will be thrown.  Note that if* <tt>name</tt> is <tt>null</tt>, this check is not performed.* You should always pass in the <a href="#name">binary name</a> of the* class you are defining as well as the bytes.  This ensures that the* class you are defining is indeed the class you think it is.** <p> The specified <tt>name</tt> cannot begin with "<tt>java.</tt>", since* all classes in the "<tt>java.*</tt> packages can only be defined by the* bootstrap class loader.  If <tt>name</tt> is not <tt>null</tt>, it* must be equal to the <a href="#name">binary name</a> of the class* specified by the byte array "<tt>b</tt>", otherwise a {@link* <tt>NoClassDefFoundError</tt>} will be thrown.  </p>** @param  name*         The expected <a href="#name">binary name</a> of the class, or*         <tt>null</tt> if not known** @param  b*         The bytes that make up the class data. The bytes in positions*         <tt>off</tt> through <tt>off len-1</tt> should have the format*         of a valid class file as defined by*         <cite>The Java™ Virtual Machine Specification</cite>.** @param  off*         The start offset in <tt>b</tt> of the class data** @param  len*         The length of the class data** @param  protectionDomain*         The ProtectionDomain of the class** @return  The <tt>Class</tt> object created from the data,*          and optional <tt>ProtectionDomain</tt>.** @throws  ClassFormatError*          If the data did not contain a valid class** @throws  NoClassDefFoundError*          If <tt>name</tt> is not equal to the <a href="#name">binary*          name</a> of the class specified by <tt>b</tt>** @throws  IndexOutOfBoundsException*          If either <tt>off</tt> or <tt>len</tt> is negative, or if*          <tt>off len</tt> is greater than <tt>b.length</tt>.** @throws  SecurityException*          If an attempt is made to add this class to a package that*          contains classes that were signed by a different set of*          certificates than this class, or if <tt>name</tt> begins with*          "<tt>java.</tt>".*/protected final Class<?> defineClass(String name, byte[] b, int off, int len,ProtectionDomain protectionDomain)throws ClassFormatError{//1.链接过程中的第一步1.1验证protectionDomain = preDefineClass(name, protectionDomain);Class c = null;//1.链接过程中的第二步1.2准备,这里就是加载class字节码了String source = defineClassSourceLocation(protectionDomain);//1.链接过程中的第三步1.3解析,这里就是通过native方法进行具体的解析了try {c = defineClass1(name, b, off, len, protectionDomain, source);} catch (ClassFormatError cfe) {c = defineTransformedClass(name, b, off, len, protectionDomain, cfe,source);}//对类进行签名postDefineClass(c, protectionDomain);return c;}/* Determine protection domain, and check that:- not define java.* class,- signer of this class matches signers for the rest of the classes inpackage.*/private ProtectionDomain preDefineClass(String name,ProtectionDomain pd){if (!checkName(name))throw new NoClassDefFoundError("IllegalName: "   name);if ((name != null) && name.startsWith("java.")) {throw new SecurityException("Prohibited package name: "  name.substring(0, name.lastIndexOf('.')));}if (pd == null) {pd = defaultDomain;}if (name != null) checkCerts(name, pd.getCodeSource());return pd;}private String defineClassSourceLocation(ProtectionDomain pd){CodeSource cs = pd.getCodeSource();String source = null;if (cs != null && cs.getLocation() != null) {source = cs.getLocation().toString();}return source;}private Class defineTransformedClass(String name, byte[] b, int off, int len,ProtectionDomain pd,ClassFormatError cfe, String source)throws ClassFormatError{// Class format error - try to transform the bytecode and// define the class again//ClassFileTransformer[] transformers =ClassFileTransformer.getTransformers();Class c = null;if (transformers != null) {for (ClassFileTransformer transformer : transformers) {try {// Transform byte code using transformerbyte[] tb = transformer.transform(b, off, len);c = defineClass1(name, tb, 0, tb.length,pd, source);break;} catch (ClassFormatError cfe2)     {// If ClassFormatError occurs, try next transformer}}}// Rethrow original ClassFormatError if unable to transform// bytecode to well-formed//if (c == null)throw cfe;return c;}private void postDefineClass(Class c, ProtectionDomain pd){if (pd.getCodeSource() != null) {Certificate certs[] = pd.getCodeSource().getCertificates();if (certs != null)setSigners(c, certs);}}

ClassLoader总结

  • ClassLoader展现了双亲委派模式的实现机制
  • ClassLoader实现了大概的类加载过程(加载和链接阶段)
  • ClassLoader在加载过程中涉及到了安全管理,类签名,lib扫描,包定义,类的访问权限,并发加载的安全性
  • ClassLoader源码总共分为下面5大部分,由于是偏底层的类,所以代码会紧凑点,不好阅读,但是比较稳定
    1.Class 的定义和加载
    2.Hierarchy 类的层次结构
    3.Resource 定义和加载
    4.Native library access (lib包访问)
    5.Package 定义

上面只是根据ClassLoader源码做了一些简单的解析,更具体的可以看下面的链接:https://blog.csdn.net/m0_38075425/article/details/81627349https://www.cnblogs.com/czwbig/p/11127222.html

架构设计@工程设计@服务稳定性之路

这篇关于JavaClassLoader源码分析(中)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/994479

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听