当前位置:网站首页>Chapter 4: talk about class loader again
Chapter 4: talk about class loader again
2022-07-06 22:18:00 【Zhang Sanfeng learns from Dugu Jiujian】
The first 4 Chapter : Let's talk about class loaders
summary
The class loader is JVM The premise of executing the class loading mechanism .
ClassLoader The role of :
ClassLoader yes Java Core components , be-all Class It's all by ClassLoader Loading ,ClassLoader Be responsible for bringing... Through various means Class The binary data stream of information is read in JVM Inside , Convert to a corresponding java.lang.Class Object instances . And then to Java Virtual machine to link 、 Initialization and other operations . therefore ,ClassLoader Throughout the loading phase , Can only affect the loading of classes , And not through ClassLoader To change the linking and initialization behavior of a class . As for whether it can run , By Execution Engine( Execution engine ) decision .
Class loaders first appeared in Java1.0 In the version , At that time, it was just for satisfaction Java Applet Developed for application . But now class loaders are OSGi、 The field of bytecode encryption and decryption is brilliant . This is mainly due to Java When the designers of virtual machines were designing class loaders , I didn't consider binding it to JVM Inside , The advantage of this is that it can perform class loading operations more flexibly and dynamically .
Big interview questions
tencent
- What is the parent delegate model ?
- What are the class loaders ?
millet
- Let's introduce the parent delegation model
sound of dripping water :
- Simply talk about the classloader you know
- one side : Let's talk about the parental delegation model , And its advantages
Bytes to beat
- What is a class loader , What are the class loaders ?
JD.COM :
What is the parental delegation model for classloaders ?
Can the parental delegation mechanism be broken ? Why?
Class loading classification
Class loading classification : Explicitly load vs Implicitly load
class Of documents Explicitly load And Implicitly load Means the way in which JVM load class File to memory mode .
- Explicit loading refers to loading in code by calling ClassLoader load class object , If used directly Class.forName(name) or this.getClass().getclassLoader( ).loadClass() load class object .
- Implicit loading is not directly invoked in code. ClassLoader Method loading class object , Instead, it is automatically loaded into memory through the virtual machine , When loading a class's class When you file , Of the class class The object of another class is referenced in the file , At this point, the extra referenced class will be passed through the JVM Automatically load into memory .
In daily development, the above two methods are usually mixed .
public class UserTest {
public static void main(String[] args) {
User user = new User(); // Implicitly load
try {
Class<?> clazz = Class.forName("com.atguigu.java.User"); // Explicitly load
ClassLoader.getSystemClassLoader().loadClass("com.atguigu.java.User"); // Explicitly load
User user1 = (User) clazz.newInstance();
user1.setId(1);
System.out.println(user1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
The necessity of class loader
In general ,Java Developers don't need to explicitly use class loaders in their programs , But it is very important to understand the loading mechanism of class loader . From the following aspects :
- Avoid problems in development java.lang.ClassNotFoundException Abnormal or java.lang.NoClassDefFoundError When abnormal , At sea . Only by understanding the loading mechanism of class loader can we quickly locate and solve problems according to the error exception log when exceptions occur
- When you need to support dynamic loading of classes or need to encrypt and decrypt the compiled bytecode file , We need to deal with classloader .
- Developers can write custom class loaders in their programs to redefine the loading rules of classes , In order to achieve some custom processing logic .
Namespace
Why class uniqueness ?
For any class , It needs to be confirmed by the class loader that loads it and the class itself Java Uniqueness in virtual machines . Every classloader , All have a separate class namespace : Compare two classes for equality , Only here Two classes are made up of the same class loader Only under the premise of loading . otherwise , Even if the two classes originate from the same Class file , Loaded by the same virtual machine , As long as their classloaders are different , Then these two classes must not be equal .
Determine whether it is the same through the loader of the custom class Class File example
User class
public class User {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
'}';
}
}
public class UserClassLoader extends ClassLoader {
private String rootDir;
public UserClassLoader(String rootDir) {
this.rootDir = rootDir;
}
/** * To write findClass The logic of the method */
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// Get the class File byte array
byte[] classData = getClassData(name);
if (classData == null) {
throw new ClassNotFoundException();
} else {
// Directly generate class object
return defineClass(name, classData, 0, classData.length);
}
}
/** * Write to get class The logic of converting files to byte streams * @param className * @return */
private byte[] getClassData(String className) {
// Read bytes of class file
String path = classNameToPath(className);
try {
InputStream ins = new FileInputStream(path);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
// Read the bytecode of class file
while ((len = ins.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
return baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/** * The full path to the class file */
private String classNameToPath(String className) {
return rootDir + "\\" + className.replace('.', '\\') + ".class";
}
public static void main(String[] args) {
String rootDir = "E:\\IdeaWorkSpace\\JVMDemo1\\chapter04\\src\\";
try {
// Create a custom class loader 1
UserClassLoader loader1 = new UserClassLoader(rootDir);
// findClass Indicates the specific... You want to load class Structure
Class clazz1 = loader1.findClass("com.atguigu.java.User");
// Create a custom class loader 2
UserClassLoader loader2 = new UserClassLoader(rootDir);
Class clazz2 = loader2.findClass("com.atguigu.java.User");
// Must be false, Because the two one. Class Classes are made up of two different ClassLoader Loaded
System.out.println(clazz1 == clazz2); //clazz1 And clazz2 Corresponding to different class template structures .
System.out.println(clazz1.getClassLoader()); // [email protected]
System.out.println(clazz2.getClassLoader()); // [email protected]
//######################
// Load using system class loader , What is loaded here is again out The following bytecode file
Class clazz3 = ClassLoader.getSystemClassLoader().loadClass("com.atguigu.java.User");
System.out.println(clazz3.getClassLoader());
System.out.println(clazz1.getClassLoader().getParent());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Namespace
- Each class loader has its own namespace , The namespace consists of the loader and all classes loaded by the parent loader
- In the same namespace , Can't The full name of the class appears ( Include the package name of the class ) The same two classes
- In different namespaces ,** There may be ** The full name of the class will appear ( Include the package name of the class ) The same two classes
In large applications , We often use this feature , To run different versions of the same class .
Basic features of class loading mechanism
Generally, the class loading mechanism has three basic characteristics :
- Parent delegation model . But not all class loads follow this model , sometimes , Start class loader (Bootstrap ClassLoader) Type loaded , It is possible to load user code , such as JDK Inside ServiceProvider/ServiceLoader Mechanism , Users can access the API On the frame , Provide your own implementation ,JDK Also need to provide some default reference implementation . for example ,Java in JNDI、JDBC、 file system 、Cipher And so on , They all use this mechanism , In this case, the parent delegation model will not be used to load , Instead, it uses a so-called context loader .
- visibility , The subclass loader can access the type loaded by the parent loader , But the reverse is not allowed . Otherwise , Because of the lack of necessary isolation , We can't use class loaders to implement container logic .
- Oneness , Because the type of the parent loader is visible to the child loader , So the type loaded in the parent loader , It will not be loaded repeatedly in the subloader . But notice , Class loader “ neighbor ” between ( At the same level , Not the same classloader ), The same type can still be loaded multiple times , Because we can't see each other .
review : Loader classification of classes ( In fact, it is divided from different dimensions )
JVM Two types of classloaders are supported , Respectively Boot class loader (Bootstrap ClassLoader) And custom class loader (User-Defined ClassLoader) .
conceptually , Custom class loaders It generally refers to a kind of classloader customized by developers in the program , however Java The virtual machine specification is not so defined , It is All derived from abstract classes ClassLoader Class loaders of are divided into custom class loaders . Regardless of the type of class loader , In the program, our most common class loader structure is as follows :
Bootstarp Class Loader
: Boot class loader 、Extension Class Loader
: Extend the classloader 、System Class Loader
: system class loader ( The last two belong toCustom class loaders
All inherited fromClassLoader
)
notes :Bootstarp ClassLoader By C/C++ Realized , Everything else is made up of Java The realization of language .
- In addition to the top-level boot loader , The rest of the class loaders should have their own “ Parent class ” loader .( notes : This is not a real inheritance )
- Different class loaders It seems to be inheritance (Inheritance) Relationship , It's actually Inclusion relation . In the lower loader , Contains a reference to the upper loader .
ExtClassLoader Of UML chart
In fact, they are not directly inherited
Boot class loader (Bootstrap ClassLoader)
The extension class loader and application class loader also need to be loaded , So who will load them ? They are loaded by the boot class loader
Use
-XX:+TraceClassLoading
Parameter print class loading information
Start class loader ( Boot class loader ,Bootstrap ClassLoader)
- This class loads using C/C++ The realization of language , Nested in JVM Inside .
- It's used to load Java The core of the library (JAVA_HOME/jre/lib/rt.jar or sun.boot.class.path The content of the path ). For providing JVM The class you need .
- Not inherited from java.lang.ClassLoader, No parent loader .
- For safety reasons ,Bootstrap The boot class loader only loads packages named java、javax、sun Class with equal beginning
- Loading extension classes and application class loaders , And designated as their parent class loader .
Start the class loader to use C++ Compiling ?Yes!
- C/C++ Pointer function & A function pointer 、C++ Support for multiple inheritance 、 More efficient
- Java: from C++ Evolved ,(C++)– edition , Single inheritance
Extend the classloader (Extension ClassLoader)
- Java Language writing , from sun.misc.Launcher$ExtClassLoader Realization .
- Inherited from ClassLoader class
- The parent loader is the boot loader
- from java.ext.dirs Load the class library in the directory specified by the system property , Or from JDK Of the installation directory jre/lib/ext Load class library under subdirectory . If the user created JAR Put it in this directory , It will also be automatically loaded by the extension class loader .
Print the loader loading path of various classes
/** * @author shkstart * @create 2020-09-15 19:13 */
public class ClassLoaderTest {
public static void main(String[] args) {
System.out.println("********** Start class loader **************");
// obtain BootstrapClassLoader Able to load api The path of
URL[] urLs = sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (URL element : urLs) {
System.out.println(element.toExternalForm());
}
// Choose a class from the path above , Let's see what his classloader is : Boot class loader
ClassLoader classLoader = java.security.Provider.class.getClassLoader();
System.out.println(classLoader); // The expected class loader cannot be obtained
System.out.println("*********** Extend the classloader *************");
String extDirs = System.getProperty("java.ext.dirs");
for (String path : extDirs.split(";")) {
System.out.println(path);
}
//
// // Choose a class from the path above , Let's see what his classloader is : Extend the classloader
ClassLoader classLoader1 = sun.security.ec.ECOperations.class.getClassLoader();
System.out.println(classLoader1);//[email protected]
}
}
result
********** Start class loader **************
file:/D:/jdk/jdk1.8.0_291/jre/lib/resources.jar
file:/D:/jdk/jdk1.8.0_291/jre/lib/rt.jar
file:/D:/jdk/jdk1.8.0_291/jre/lib/sunrsasign.jar
file:/D:/jdk/jdk1.8.0_291/jre/lib/jsse.jar
file:/D:/jdk/jdk1.8.0_291/jre/lib/jce.jar
file:/D:/jdk/jdk1.8.0_291/jre/lib/charsets.jar
file:/D:/jdk/jdk1.8.0_291/jre/lib/jfr.jar
file:/D:/jdk/jdk1.8.0_291/jre/classes
null
*********** Extend the classloader *************
D:\jdk\jdk1.8.0_291\jre\lib\ext
C:\WINDOWS\Sun\Java\lib\ext
sun.misc.Launcher$ExtClassLoader@38af3868
Process finished with exit code 0
system class loader / Apply the class loader (AppClassLoader)
AppClassLoader Inheritance relationship of , You can compare the above ExtClassLoader,AppClassLoader and ExtClassLoader, It's not inheritance , Is juxtaposition , It can only be said to be a superior subordinate relationship .
Application class loader ( system class loader ,AppClassLoader)
- java Language writing , from sun.misc.Launcher$AppClassLoader Realization
- Inherit ClassLoader class
- The parent class loader is an extended class loader ( But there is no inheritance )
- It's responsible for loading environment variables classpath Or system properties java.class.path Specify the class library under the path
- It is the default parent loader for user-defined class loaders
- adopt ClassLoader Of getSystemClassLoader() Method to get the class loader
User defined class loader
- stay Java In daily application development , Class loading is almost done by 3 Class loaders work with each other . When necessary , We can also customize the classloader , To customize how classes are loaded .
- reflect Java One of the key factors of language's great vitality and charm is ,Java Developers can customize class loader to realize dynamic loading of class library , The load source can be local JAR package , It can also be a remote resource on the network .
- Through the class loader, you can achieve a very wonderful plug-in mechanism , There are numerous practical cases in this field . for example , The famous OSGI Component framework , Again Eclipse Plug in mechanism of . Class loaders provide a mechanism for applications to dynamically add new functions , This mechanism can be implemented without repackaging and publishing applications .
- meanwhile , Custom loader can achieve application isolation , for example Tomcat,Spring And so on middleware and component framework have realized the custom loader inside , And separate different component modules through custom loader . This kind of mechanism is better than others C/C++ The program is so much better , I don't want to change it C/C++ The program can add new functions to it , It's almost impossible , Just one compatibility can stop all good ideas .
- Custom class loaders usually need to inherit ClassLoader.
Test loaders for different classes
every last Class The object will contain a... That defines it ClassLoader A reference to .
obtain ClassLoader Way
Get the... Of the current class ClassLoader clzz.getClassLoader() |
---|
Gets the context of the current thread ClassLoader Thread.currentThread().getContextClassLoader() , This defaults to the system class loader |
Get system's ClassLoader ClassLoader.getSystemClassLoader() |
Test code
stay Java The data types of are divided into basic data types and reference data types , The basic data type is pre-defined by the virtual machine , The reference data type needs to load the class .
/** * Created with IntelliJ IDEA. * @Author: Amani * @Date: 2022/07/02 20:43 * @Version:1.0 * */
public class ClassLoaderTest1 {
public static void main(String[] args) {
// Get system classloader
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println("systemClassLoader = " + systemClassLoader);
// Get extended class loader
ClassLoader extClassLoader = systemClassLoader.getParent();
System.out.println("extClassLoader = " + extClassLoader);
// Get boot class loader : Failure , Because it was C/C++ Compiling
ClassLoader bootstrapClassLoader = extClassLoader.getParent();
System.out.println("parent = " + bootstrapClassLoader);
// #########################
try {
Class<?> clazz = Class.forName("java.lang.String");
ClassLoader classLoader = clazz.getClassLoader();
System.out.println("classLoader = " + classLoader);
// The custom type uses the system class loader by default
Class<?> clazz1 = Class.forName("com.atguigu.java.ClassLoaderTest1");
ClassLoader classLoader1 = clazz1.getClassLoader();
System.out.println("classLoader1 = " + classLoader1); // Self defined default is system class loader
String[] str = new String[10];
// null, Indicates that the bootloader is used (BootstrapClassLoader), In fact, this is related to the class loader of array elements
System.out.println("str Of ClassLoader yes " + str.getClass().getClassLoader());
ClassLoaderTest1[] arr1 = new ClassLoaderTest1[10];
System.out.println("arr1 Of ClassLoader yes " + arr1.getClass().getClassLoader()); // AppClassLoader
int[] arr2=new int[10];
System.out.println("arr2 Of ClassLoader yes "+arr2.getClass().getClassLoader()); // null , Basic data types do not need to be loaded
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Be careful :
- You can find from the above code , If it's a custom class , Then it is made of system class loader Loading
- The loader of an array class is determined by the elements of the array , If it looks like String And other core class libraries , their getClassLoader() It will be empty , Because their classloader is the boot classloader
- Array of basic data types getClassLoader() It's also null, Because they are predefined by virtual machines
ClassLoader Source code analysis
ClassLoader Relationship with existing class loaders :
In addition to the loader of the above virtual machine , Users can also customize their own class loaders .Java Abstract classes are provided java.lang.ClassLoader, All user-defined class loaders should inherit ClassLoader class .
Of the two parent delegation model Java translate , Excerpt from jdk Source code
/* * <p> Class loaders may typically be used by security managers to indicate * security domains. * * <p> The <tt>ClassLoader</tt> class uses a delegation model to search for * classes and resources. Each instance of <tt>ClassLoader</tt> has an * associated parent class loader. When requested to find a class or * resource, a <tt>ClassLoader</tt> 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 <tt>ClassLoader</tt> instance. * * <p> Class loaders that support concurrent loading of classes are known as * <em>parallel capable</em> class loaders and are required to register * themselves at their class initialization time by invoking the * {@link * #registerAsParallelCapable <tt>ClassLoader.registerAsParallelCapable</tt>} * method. Note that the <tt>ClassLoader</tt> class is registered as parallel * capable by default. However, its subclasses still need to register themselves * if they are parallel capable. <br> * 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 {@link #loadClass * <tt>loadClass</tt>} methods). */
adopt Launcher To create ExtClassLoader and AppClassLoader, Below is Launcher Constructor
public Launcher() {
Launcher.ExtClassLoader var1;
try {
var1 = Launcher.ExtClassLoader.getExtClassLoader(); // establish ExtClassLoader
} catch (IOException var10) {
throw new InternalError("Could not create extension class loader", var10);
}
try {
this.loader = Launcher.AppClassLoader.getAppClassLoader(var1); // adopt ExtClassLoader establish AppClassLoader
} catch (IOException var9) {
throw new InternalError("Could not create application class loader", var9);
}
Thread.currentThread().setContextClassLoader(this.loader); // Loader of the class used to set the context , It's the one above AppClassLoader
String var2 = System.getProperty("java.security.manager");
if (var2 != null) {
SecurityManager var3 = null;
if (!"".equals(var2) && !"default".equals(var2)) {
try {
var3 = (SecurityManager)this.loader.loadClass(var2).newInstance();
} catch (IllegalAccessException var5) {
} catch (InstantiationException var6) {
} catch (ClassNotFoundException var7) {
} catch (ClassCastException var8) {
}
} else {
var3 = new SecurityManager();
}
if (var3 == null) {
throw new InternalError("Could not create SecurityManager: " + var2);
}
System.setSecurityManager(var3);
}
}
ExtClassLoader Of parent yes null
public ExtClassLoader(File[] var1) throws IOException {
super(getExtURLs(var1), (ClassLoader)null, Launcher.factory);
SharedSecrets.getJavaNetAccess().getURLClassPath(this).initLookupCache(this);
}
AppClassLoader Yes, it will ExtClassLoader As parent Pass in , Create AppClassLoader object
static class AppClassLoader extends URLClassLoader {
final URLClassPath ucp = SharedSecrets.getJavaNetAccess().getURLClassPath(this);
public static ClassLoader getAppClassLoader(final ClassLoader var0) throws IOException {
final String var1 = System.getProperty("java.class.path");
final File[] var2 = var1 == null ? new File[0] : Launcher.getClassPath(var1);
return (ClassLoader)AccessController.doPrivileged(new PrivilegedAction<Launcher.AppClassLoader>() {
public Launcher.AppClassLoader run() {
URL[] var1x = var1 == null ? new URL[0] : Launcher.pathToURLs(var2);
return new Launcher.AppClassLoader(var1x, var0);
}
});
}
AppClassLoader(URL[] var1, ClassLoader var2) {
super(var1, var2, Launcher.factory);
this.ucp.initLookupCache(this);
}
Loader of the class in the current thread context , yes AppClassLoader
ClassLoader Main methods
abstract class classLoader Main methods :( There are no abstract methods inside )
getParent() Method resolution
- getParent() Method resolution
@CallerSensitive
public final ClassLoader getParent() {
if (parent == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// Check access to the parent class loader
// If the caller's class loader is same as this class loader,
// permission check is performed.
checkClassLoaderPermission(parent, Reflection.getCallerClass());
}
return parent;
}
loadClass Analysis of
- Returns the superclass loader of this loader ,loadClass Analysis of , The load name is name Class , The return result is java.lang.Class Class . If the class is not found , Then return to ClassNotFoundException. The logic of this method is the implementation of the parent delegation pattern .( rewrite loadClass() Method , You can break the parental delegation mechanism )
// The parameter passed in is the full class name , It can be from disk , There can also be binary stream data transmitted from the network
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
- Heavy duty loaderClass Method
Here is the combined loading ClassLoader.getSystemClassLoader().loadClass(“com.atguigu.java.User”); To analyze
First, Bootstrap ClassLoader Loading ; If it cannot be loaded , Just ExtClassLoader Loading , If it can't load , Just from AppClassLoader Loading
ClassLoader.getSystemClassLoader().loadClass("com.atguigu.java.User");
/** * @param name Represents the full class name of the class to be loaded * @param resolve Indicates whether parsing operation is required during loading , * true Indicates that it needs to be parsed * false Indicates that parsing is not required */
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// Synchronous operation , Ensure that it can only be loaded once
// First, judge whether the class with the same name has been loaded in the cache
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
// Get the loader of the parent class of the current class loader
if (parent != null) {
// Here is recursion
// That is, the embodiment of the parental delegation mechanism , If there is a parent loader , Then call the parent class loader to load
c = parent.loadClass(name, false);
} else {
// parent by null: The parent class loader is the boot class loader
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// The parent class loader of the loader of the current class does not load this class or The loader of the current class does not load this class
// Call current ClassLoader Of findClass()
// 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) {
// Whether to perform parsing operation
resolveClass(c);
}
return c;
}
}
findClass() Method resolution
- findClass() Method resolution
This is a ClassLoader Medium findClass() Method
protected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}
- URLClassLoader Rewritten in findClass
protected Class<?> findClass(final String name)
throws ClassNotFoundException
{
final Class<?> result;
try {
result = AccessController.doPrivileged(
new PrivilegedExceptionAction<Class<?>>() {
public Class<?> run() throws ClassNotFoundException {
String path = name.replace('.', '/').concat(".class");
Resource res = ucp.getResource(path, false);
if (res != null) {
try {
// call defineClass Method , To generate a Class example
return defineClass(name, res);
} catch (IOException e) {
throw new ClassNotFoundException(name, e);
}
} else {
return null;
}
}
}, acc);
} catch (java.security.PrivilegedActionException pae) {
throw (ClassNotFoundException) pae.getException();
}
if (result == null) {
throw new ClassNotFoundException(name);
}
return result;
}
Find binary name as name Class , The return result is java.lang.Class Class . It's a protected way ,JVM Encourage us to rewrite this method , You need to customize the loader to follow the parental delegation mechanism , This method will be checked after the parent loader loadClass() Method call .
stay JDK1.2 Before , stay Custom class loading when , Always inherit ClassLoader Class and rewrite loadClass Method , So as to implement the custom class loading class . But in JDK1.2 After that, users are no longer recommended to overwrite loadClass() Method , Instead, it is recommended to write the custom class loading logic in findClass() In the method , From the previous analysis, we can see ,findclass() The method is in loadClass() Called in method , When loadClass() Method after the parent loader fails to load , Will call your own findClass() Method to complete class loading , This ensures that the custom classloader also conforms to the parental delegation mode .
It should be noted that ClassLoader Class is not implemented findClass() Method , Instead, throw
ClassNotFoundException abnormal , At the same time, we should know findClass The way is usually with defineClass Methods used together . In general , When customizing class loaders , Will directly cover ClassLoader Of findClass() Method and write the loading rules , Get the bytecode of the class to be loaded and convert to stream , And then call defineClass() Method to generate the class Class object .
URLClassLoader Medium defineClass() Method
- URLClassLoader Medium defineClass() Method , Used to generate Class example
private Class<?> defineClass(String name, Resource res) throws IOException {
long t0 = System.nanoTime();
int i = name.lastIndexOf('.');
URL url = res.getCodeSourceURL();
if (i != -1) {
String pkgname = name.substring(0, i);
// Check if package already loaded.
Manifest man = res.getManifest();
definePackageInternal(pkgname, man, url);
}
// Now read the class bytes and define the class
java.nio.ByteBuffer bb = res.getByteBuffer();
if (bb != null) {
// Use (direct) ByteBuffer:
CodeSigner[] signers = res.getCodeSigners();
CodeSource cs = new CodeSource(url, signers);
sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
return defineClass(name, bb, cs);
} else {
byte[] b = res.getBytes();
// must read certificates AFTER reading bytes.
CodeSigner[] signers = res.getCodeSigners();
CodeSource cs = new CodeSource(url, signers);
sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
return defineClass(name, b, 0, b.length, cs);
}
}
- findClass Simply rewrite by yourself
/** * To write findClass The logic of the method */
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// Get the class File byte array
byte[] classData = getClassData(name);
if (classData == null) {
throw new ClassNotFoundException();
} else {
// Directly generate class object
return defineClass(name, classData, 0, classData.length);
}
}
SecureClassLoader And URLClassLoader
next SecureClassLoader Expanded ClassLoader, Several new code sources related to use are added ( The location of the code source and its Certificate verification ) and Permission definition class validation ( Mainly refers to right class Access to source code ) Methods , Generally, we don't deal with this kind of things directly , More with its subclasses URLClassLoader There's a connection .
As I said before ,ClassLoader Is an abstract class , Many methods are empty and not implemented , such as findClass()、findResource() etc. . and URLClassLoader This implementation class provides specific implementations for these methods . And added URLClassPath Class to help get Class Byte stream and other functions . When writing custom class loaders , If there are not too complex requirements , Can inherit directly URLClassLoader class , In this way, you can avoid writing by yourself findclass() Method and the way to get the byte stream , Make the custom class loader more concise .
ExtClassLoader And AppClassLoader
To understand the URLClassLoader Next, look at the remaining two class loaders , namely Extended class loader ExtClassLoader And system class loader AppClassLoader, These two classes Inherit from URLClassLoader, yes sun.misc.Launcher The static inner class of .
sun.misc.Launcher Mainly used by the system to start the main application ,ExtClassLoader and AppClassLoader It's all by sun.misc.Launcher Created , The main class structure is as follows :
We found that ExtClassLoader I didn't rewrite it loadClass() Method , This is enough to show that it follows the parental delegation model , and AppClassLoader Reload the loadclass() Method , But in the end, the parent class is called loadClass() Method , Therefore, we still abide by the parental appointment model .
Class.forName() And ClassLoader Of loadClass()
Dachang asked
- Class.forName(): It's a static method , The most common is Class.forName(String className); Returns a value based on the fully qualified name of the class passed in Class object . This method will Class When the file is loaded into memory , Class initialization will be performed . Such as :
Class.forName( “com.atguigu.java.Helloworld” );( Will actively use this class , Initialize this class , Generated <client> Method ) - ClassLoader Of loadClass(): This is an example method , Need one ClassLoader Object to call the method . This method will
Class When the file is loaded into memory , Class initialization is not performed , This class is not initialized until it is first used . This method needs to get a ClassLoader object , So you can specify which class loader to use as needed . Such as :ClassLoader cl=… .;
c1.loadClass( “com.atguigu.java.Helloworld” );( Will not actively use this class , Because this class is not initialized , No generation <client> Method )
Parent delegate mechanism
Definition and essence
Class loaders are used to load classes into Java In the virtual machine . from JDK1.2 Version start , The loading process of the class adopts the parental delegation mechanism , This kind of mechanism can better guarantee the safety Java Platform security .
- Definition
If a class loader receives a request to load a class , It doesn't try to load the class itself first , Instead, the request task is delegated to the parent loader , Recursion in turn , If the parent loader can complete the class loading task , You're back . Only when the parent loader cannot complete this load task , Just load it yourself .
- The essence
Specifies the order of class loading : Boot class loader loads first , If it doesn't load , Loaded by extension class loader , If it doesn't load yet , Will be loaded by system classloader or custom classloader .
Advantages and disadvantages
- Avoid duplicate loading of classes , Ensure the global uniqueness of the class
Java Class has a hierarchical relationship with priority along with its classloader , Through this level, we can avoid the repeated loading of classes , When the father has loaded the class , There is no need ClassLoader Load again .
- Ensure program safety , Prevention core API Be tampered with at will
Code support
The parental delegation mechanism is in java.lang.ClassLoader.loadClass(String,boolean) Interface . The logic of the interface is as follows :
- First, find out whether there is a target class in the cache of the current loader , If there is , Go straight back to .
- Determine whether the parent loader of the current loader is empty , If it's not empty , Call parent.loadClass(name,false) Interface to load .
- conversely , If the parent of the current loader is empty , Call findBootstrapClassOrNull(name) Interface , Let the boot class loader do .
- If you pass the above 3 All paths failed to load , Call findClass(name) Interface to load . The interface will eventually call java.lang.ClassLoader Interface defineClass Series of native Interface load target Java class .
The model of parental delegation is hidden in this section 2 And the 3 In step .
give an example
Suppose that the current load is java.lang.object This class , Obviously , This category belongs to JDK The core experience can no longer be a core class , So it must only be loaded by the bootloader . When JVM Ready to load java.lang .Object when ,JVM By default, the system classloader will be used to load , According to the above 4 Step loading logic , In the 1 Step 1: you can't find this class from the cache of the system class , So we go to the second 2 Step . Since the parent loader of the slave system class loader is an extended class loader , So the extension class loader continues from the 1 Step to repeat . Because the class cannot be found in the cache of the extension class loader , So go to the second stage 2 Step . The parent loader of the extension class is null, So the system calls findClass(string), Finally, it is loaded by bootloader .
reflection
If overridden in a custom class loader java.lang.ClassLoader.loadClass(String) or java.lang.ClassLoader.loadClass(String, boolean) Method , Remove the parental appointment mechanism , Just keep the above one 4 Step 2 1 Step and step 4 Step , Is it possible to load the core class library ?
It's not going to work ! because JDK It also provides a layer of protection mechanism for the core class library . Whether it's a custom class loader , Or system class loader or extended class loader , Must be called in the end java.lang.ClassLoader.defineClass(String, byte[], int, int,
ProtectionDomain) Method , And the method does preDefineClass() Interface , The interface provides the JDK Protection of core class library .
protected final Class<?> defineClass(String name, byte[] b, int off, int len,
ProtectionDomain protectionDomain)
throws ClassFormatError
{
protectionDomain = preDefineClass(name, protectionDomain);
String source = defineClassSourceLocation(protectionDomain);
Class<?> c = defineClass1(name, b, off, len, protectionDomain, source);
postDefineClass(c, protectionDomain);
return c;
}
The disadvantages of the parental entrustment model
The delegate process of checking whether a class is loaded is one-way , This way is relatively clear in structure , Make each ClassLoader Our responsibilities are very clear , But there is also a problem , namely top-level ClassLoader Unable to access underlying ClassLoader The class loaded .
Usually , The classes in the bootloader are the core classes of the system , Including some important system interfaces , In the application class loader , For application class . Follow this pattern , There is no problem for application class to access system class , But there will be problems when the system class accesses the application class . For example, an interface is provided in the system class , The interface needs to be implemented in the application class , The interface also binds a factory method , An instance used to create the interface , Both interfaces and factory methods are starting the class loader (Bootstrap ClassLoader) in . At this time , The factory method cannot be created and loaded by the application class loader (AppClassLoader) Problems of application examples of .
Conclusion
because Java The virtual machine specification does not explicitly require that the loading mechanism of class loaders must use the parental delegation model , It's just a suggestion . For example **Tomcat in **, The loading mechanism of class loader is different from the traditional parental delegation model , When the default class loader receives a class load task , First, it loads itself , When it fails to load , The class loading task will be delegated to its superclass loader for execution , It's also Servlet A method of standard recommendation .
Break the parental delegation mechanism
Break the parental delegation mechanism 1
The parental delegation model is not a model with mandatory constraints , It is Java The implementation of class loader recommended by designers to developers .
stay Java Most of the world's classloaders follow this model , But there are exceptions , until Java Until modularity came into being , The model of parent delegation mainly appeared 3 The second is larger “ Be destroyed ” The situation of .
The first time to destroy the mechanism of parents' appointment :
The first time a parent delegation model “ Be destroyed ” In fact, it happened before the emergence of the parental delegation model —— namely JDK 1.2 Before it came out “ ancient ” Time .
Because the parent delegation model is in JDK1.2 Then it was introduced , But the concept of class loaders and abstract classes java.lang.ClassLoader It's in Java In the first version of , Facing the existing user-defined class loader code ,Java Designers have to make some compromises when introducing the parental delegation model , In order to be compatible with the existing code , There is no longer a technical means to avoid loadClass() The possibility of being covered by subclasses , Only in JDK1.2 After that java.lang.ClassLoader Add a new protected Method findClass(), And guide the user to rewrite this method as much as possible when loading the class logic , Not in loadClass() Code in . We have analyzed in the last section loadClass() Method , The specific logic of parental appointment is realized here , according to loadClass() The logic of the method , If the parent class fails to load , Will automatically call your own findClass() Method to complete the load , This does not affect users to load classes according to their own wishes , It can also ensure that the newly written class loader is in line with the parental delegation rules .
Break the parental delegation mechanism 2: Thread context class loader
The second time of the parent delegation model “ Be destroyed ” It is due to the defects of the model itself , Parent delegation solves the problem of consistency of basic types in the cooperation of various class loaders ( The more basic class is loaded by the higher loader ), The basis type is called “ Basics ”, Because they are always inherited by user code 、 Called API There is , But programming often does not have absolutely invariable perfect rules , If there is an underlying type, it will call back to the user's code , So what should we do ?
It's not impossible , A typical example is JNDI service ,JNDI Now it is Java Standard services , Its code is loaded by the boot loader ( stay DK 1.3 To join in rt.jan Of ), It must belong to Java It's a very basic type . but JNDI The purpose of existence is to search and centralize the management of resources , It needs to call the ClassPath Under the JNDI Service provider interface (Service Provider Interface,SPI) Code for , Now comes the question , It's impossible to start a class loader 、 Loading the code , So what do we do? ?(SPI: stay Java In the platform , The core class rt.jar Provide external services in 、 Interfaces that can be implemented by the application layer are called SPI)
To solve this dilemma ,Java Our design team had to introduce a less elegant design : Thread context class loader (Thread Context
ClassLoader). This class loader can be used through java.lang.Thread Class setContextClassLoader() Method to set , If the thread is not set when it is created , It will inherit a... From the parent thread , If it has not been set in the global scope of the application , Then this class loader is the application class loader by default .
With thread context class loader , The program can do some “ Fraud ” It's something .JNDI The service uses this thread context class loader to load the required SPI Service code , This is the behavior of the parent class loader asking the child class loader to complete the class loading , This behavior actually breaks through the hierarchy of the parent delegation model to reverse the use of class loaders , Has violated the general principles of the parental delegation model , But it's also a helpless thing .Java It's about SPI The loading of is basically done in this way , for example NDI、JDBC、3CE、JAXB and B1 etc. . however , When SPI When you have more than one service provider , The code can only be hard coded according to the type of specific provider , In order to eliminate this very inelegant implementation , stay JDK 6 when ,JDK Provides java.util.ServiceLoader class , With META-INF/services Configuration information in , Supported by the chain of responsibility model , This is for SPI The loading of provides a relatively reasonable solution .
The default context loader is the application class loader , In this way, the loader is the intermediary , So that the code in the boot loader can also access the classes in the application loader .
For the third time, the mechanism of appointing parents was destroyed :
The third time the parent delegation model “ Be destroyed ” It is due to the user's pursuit of program dynamics . Such as :** Code hot swap (Hot Swap)、 Module hot deployment (Hot Deployment)** etc.
IBM Company led JSR-291( namely OSGi R4.2) The key to realize modular hot deployment is the implementation of its custom classloader mechanism , Every program module (OSGi called Bundle) All have their own classloader , When you need to replace one Bundle when , Just put Bundle Replace with the same kind of loader to realize the hot replacement of code . stay OSGi In the environment , Class loaders are no longer the tree structure recommended by the parental delegation model , But further developed into more complex Network structure .
When a class load request is received ,OSGi Class search will be done in the following order :
1) Will be with java.* Initial class , Delegate to parent loader to load .
2) otherwise , The class in the list will be delegated , Delegate to parent loader to load .
3) otherwise , take Import Classes in the list , Delegate to Export This class of Bundle Class loader loading .
4) otherwise , Find the current Bundle Of ClassPath, Use your own classloader to load .
5) otherwise , Find out if the class is in its own Fragment Bundle in , If in , To Fragment Bundle Class loader loading .6) otherwise , lookup Dynamic Import List Bundle, Delegate to the corresponding Bundle Class loader loading .
7) otherwise , Class lookup failed .
explain : Only the first two points are still consistent with the principle of parental delegation model , The rest of the class lookups are done in a flat classloader
Summary
here , We used “ Be destroyed ” This word is used to describe the above behaviors that do not conform to the principles of the parental delegation model , but here “ Be destroyed ” It's not necessarily derogatory . As long as there is a clear purpose and a good reason , Breaking through the old principles is undoubtedly an innovation .
just as :OSGi The design of class loader in is not in line with the traditional parental delegation class loader architecture , And there are still many controversies in the industry about the extra high complexity brought by its hot deployment , However, technical personnel who have an understanding of this aspect can basically reach a consensus , Think
OSGi The application of class loader in is worth learning , I totally understand OSGi The implementation of the , Even if you have mastered the essence of class loader .
Implementation of hot replacement
Hot replacement refers to the process of running the program , Don't stop service , Modify the behavior of a program only by replacing the program file . The key requirement of hot replacement is that the service cannot be interrupted , Changes must be immediately reflected in the running system . Basically, most scripting languages are inherently hot swappable , such as : PHP, Just replace it PHP Source file , This change will take effect immediately , Without having to restart Web The server .
But yes Java Come on , Hot swapping is not inherently supportive , If a class has been loaded into the system , By modifying the class file , It's not possible for the system to load and redefine this class again . therefore , stay Java A feasible way to realize this function is to use it flexibly ClassLoader.
According to this feature , It can be used to simulate the implementation of hot swap , The basic idea is shown in the following figure :
Code example :
- Loaders for custom classes
/** * @author shkstart * @create 11:08 */
public class LoopRun {
public static void main(String args[]) {
while (true) {
try {
//1. Create an instance of the custom class loader
MyClassLoader loader = new MyClassLoader("E:\\IdeaWorkSpace\\JVMDemo1\\chapter04\\src\\");
//2. Load the specified class , There is no parental delegation mechanism , It's self-defined
Class clazz = loader.findClass("com.atguigu.java1.Demo1");
//3. Create an instance of the runtime class
Object demo = clazz.newInstance();
//4. Get the method specified in the runtime class
Method m = clazz.getMethod("hot");
//5. Call the specified method
m.invoke(demo);
// sleep 5s, That is, every 5s Do it once
Thread.sleep(5000);
} catch (Exception e) {
System.out.println("not find");
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
}
- Loaded classes
/** * @author shkstart * @create 11:07 */
public class Demo1 {
public void hot() {
System.out.println("OldDemo1---> NewDemo12121");
}
}
Sandbox security mechanism
Sandbox security mechanism
- Protect program security
- Protect Java Native JDK Code
Java The core of the security model is Java The sandbox (sandbox). What is a sandbox ? Sandbox is an environment that limits the running of programs .
Sandbox mechanism is to make Java Code Limited to virtual machines (JVM) Within a specific operating range , And strictly restrict code access to local system resources . Through such measures to ensure the limited isolation of the code , Prevent damage to the local system .
Sandbox mainly restricts access to system resources , What are the system resources ?CPU、 Memory 、 file system 、 The Internet . Different levels of sandbox have different restrictions on access to these resources .
be-all Java The sandbox can be specified when the program is running , You can customize the security policy .
JDK1.0 period
stay Java The execution program is divided into local code and remote code , Native code is considered trustworthy by default , Remote code is considered untrusted . Local code for credit , Access to all local resources . And for non credit remote code in the early Java In the implementation , Security depends on sandbox (Sandbox) Mechanism . As shown in the figure below JDK1.0 Security model
JDK1.1 period
JDK1.0 Such a strict security mechanism also brings obstacles to the function expansion of the program , For example, when a user wants remote code to access files on the local system , Just go and realize .
So in the following Java1.1 In the version , The security mechanism has been improved , Added The security policy . Allows users to specify code access to local resources . As shown in the figure below JDK1.1 Security model
JDK1.2 period
stay Java1.2 In the version , Once again, the security mechanism has been improved , increase Added code signature . Whether it's local code or remote code , Will be set according to the user's security policy , It is loaded by the class loader into the runspace with different permissions in the virtual machine , To achieve differentiated code execution authority control . As shown in the figure below JDK1.2 Security model
JDK1.6 period
At present, the latest security mechanism is implemented , It introduces ** Domain (Domain)** The concept of .
The virtual opportunity loads all the code into different System domain and application domain . The system domain part is responsible for interacting with key resources , And each The application domain part accesses all kinds of needed resources through the partial proxy of the system domain . Different protected domains in the virtual machine (Protected Domain), Corresponding to different permissions (Permission). Class files in different domains have all the permissions of the current domain , As shown in the figure below , The latest security model (jdk1.6)
Loaders for custom classes
Why custom class loaders ?
- Isolation loading class
In some frameworks, middleware is isolated from application modules , Load classes into different environments . such as : A container framework in arene ensures Application Rely on the jar The package will not affect middleware Used at run time jar package . Another example :Tomcat This kind of web application server , Several kinds of loaders are customized internally , Used to isolate the same web Different applications on the application server .( Class arbitration → Class conflict )
- Modify the way the class is loaded
Class loading model is not mandatory , except Bootstrap Outside , Other loads do not have to introduce , Or according to the actual situation at a certain point in time for dynamic loading on demand
- Extended load source
For example, from the database 、 The Internet 、 Even the TV set-top box loads
- Prevent source code leakage
Java Code is easy to compile and tamper with , It can be compiled and encrypted . Then class loading also needs customization , Restore encrypted bytecode .
Common scenes
- Implement similar in-process isolation , The class loader is actually used as a different namespace , To provide similar containers 、 Modular effect . for example , Two modules depend on different versions of a class library , If they are loaded in different containers , So that they don't interfere with each other . What is the epitome of this Java EE and OSGI、JPMS Other framework .
- Applications need to get class definition information from different data sources , For example, network data sources , Not the local file system . Or you need to manipulate bytecode by yourself , Dynamically modify or generate types .
Implement the loader of custom classes
Users can customize their own class loader , In this way, the loading rules of the class can be redefined , In order to achieve some custom processing logic .
Realization way
- Java Abstract classes are provided java.lang.ClassLoader, All user-defined class loaders should inherit ClassLoader class .
- In the custom classLoader When is a subclass of , There are two common approaches :
- Method 1 : rewrite loadClass() Method ( This will destroy the parental delegation mechanism , If the parent ClassLoader Can't load this class , that loadClass() Is to call findClass() To find the current class ClassLoader)
- Method 2 : rewrite findClass() Method ( It will not destroy the parental delegation mechanism , This is to load the specified class , Then generate a Class example )( recommend )
Let's review loadClass() Source code
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;
}
}
contrast
The two methods are essentially similar , After all loadClass() Will also call findClass(), But logically, we'd better not modify it directly
loadClass() The internal logic of . The proposed approach is only to findClass() Override the loading method of custom class in , Specifies the name of the class according to the parameter , Return the corresponding Class References to objects .
reason : Because rewriting findClass() It will not destroy the parental delegation mechanism
- loadClass() This approach is where the logic of the parental delegation model is implemented , Modifying this method without authorization will cause the model to be destroyed , Easy to cause problems . Therefore, we'd better make small-scale changes within the framework of parent delegation model , The original stable structure will not be destroyed . meanwhile , It also avoids rewriting itself loadClass() Method must write duplicate code for parent delegate , From the perspective of code reusability , It's always better not to modify this method directly .
- After the custom class loader is written , Can be invoked in the program. loadClass() Method to implement the class loading operation .
explain
- Its parent class loader is the system class loader (AppClassLoader)
- JVM All class loads in use java.lang.ClassLoader.loadClass(String) Interface ( Custom class loader and override java.lang.classLoader.loadClass(String) Interface exception ), even JDK The core class library of is no exception .
Loaders for custom classes
/** * Created with IntelliJ IDEA. * @Author: Amani * @Date: 2022/07/04 22:00 * @Version:1.0 * Customize ClassLoader * */
public class MyClassLoader extends ClassLoader {
private String byteCodePath;
public MyClassLoader() {
}
public MyClassLoader(String byteCodePath) {
this.byteCodePath = byteCodePath;
}
public MyClassLoader(ClassLoader parent, String byteCodePath) {
super(parent);
this.byteCodePath = byteCodePath;
}
/** * rewrite findClass Method * @param className * @return * @throws ClassNotFoundException */
@Override
protected Class<?> findClass(String className) {
// Get the full path of bytecode file
String fileName = byteCodePath + className + ".class";
BufferedInputStream bis = null;
ByteArrayOutputStream baos = null;
try {
// Get an input stream
bis = new BufferedInputStream(new FileInputStream(fileName));
// Get the output stream of a byte array
baos = new ByteArrayOutputStream();
// The following steps are the specific process of reading in data and writing out
int len;
byte[] data = new byte[1024];
while ((len = bis.read(data)) != -1) {
// take BufferedInputStream The data in is written to ByteArrayOutputStream in
baos.write(data, 0, len);
}
// Get the data of the complete byte array in memory
byte[] byteCodes = baos.toByteArray();
// call defineClass(), Convert a byte array to Class example
Class<?> clazz = defineClass(null, byteCodes, 0, byteCodes.length);
return clazz;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (baos != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// Something unusual happened return null;
return null;
}
}
/** * Created with IntelliJ IDEA. * @Author: Amani * @Date: 2022/07/04 22:06 * @Version:1.0 * */
public class MyClassLoaderTest{
public static void main(String[] args) {
MyClassLoader classLoader = new MyClassLoader("E:\\IdeaWorkSpace\\JVMDemo1\\chapter04\\src\\com\\atguigu\\java1\\");
try {
Class<?> clazz = classLoader.loadClass("Demo1");
System.out.println(" The loader that loads this class is :" + clazz.getClassLoader().getClass().getName());
System.out.println(" The parent class of the loader that loads this class is :" + clazz.getClassLoader().getParent().getClass().getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Output results
The loader that loads this class is :com.atguigu.java2.MyClassLoader
The parent class of the loader that loads this class is :sun.misc.Launcher$AppClassLoader
边栏推荐
- AI 企业多云存储架构实践 | 深势科技分享
- GNN, please deepen your network layer~
- Unity3D学习笔记6——GPU实例化(1)
- 第3章:类的加载过程(类的生命周期)详解
- Unity3d Learning Notes 6 - GPU instantiation (1)
- Report on technological progress and development prospects of solid oxide fuel cells in China (2022 Edition)
- Some problems about the use of char[] array assignment through scanf..
- 新入职一家公司需要去实践和注意的内容
- Common sense: what is "preservation" in insurance?
- Insert sort and Hill sort
猜你喜欢
ResNet-RS:谷歌领衔调优ResNet,性能全面超越EfficientNet系列 | 2021 arxiv
硬件開發筆記(十): 硬件開發基本流程,制作一個USB轉RS232的模塊(九):創建CH340G/MAX232封裝庫sop-16並關聯原理圖元器件
GPS从入门到放弃(十二)、 多普勒定速
嵌入式常用计算神器EXCEL,欢迎各位推荐技巧,以保持文档持续更新,为其他人提供便利
GPS from getting started to giving up (19), precise ephemeris (SP3 format)
2500个常用中文字符 + 130常用中英文字符
Leetcode learning records (starting from the novice village, you can't kill out of the novice Village) ---1
二叉(搜索)树的最近公共祖先 ●●
GPS du début à l'abandon (XIII), surveillance autonome de l'intégrité du récepteur (raim)
Bat script learning (I)
随机推荐
Some problems about the use of char[] array assignment through scanf..
Management background --2 Classification list
AI 企业多云存储架构实践 | 深势科技分享
数据处理技巧(7):MATLAB 读取数字字符串混杂的文本文件txt中的数据
Oracle性能分析3:TKPROF简介
GPS from getting started to giving up (XIII), receiver autonomous integrity monitoring (RAIM)
Assembly and Interface Technology Experiment 6 - ADDA conversion experiment, AD acquisition system in interrupt mode
Insert sort and Hill sort
Memorabilia of domestic database in June 2022 - ink Sky Wheel
Solve project cross domain problems
Four data streams of grpc
Earned value management EVM detailed explanation and application, example explanation
搜素专题(DFS )
MariaDb数据库管理系统的学习(一)安装示意图
GPS from getting started to giving up (XX), antenna offset
Method return value considerations
ZABBIX proxy server and ZABBIX SNMP monitoring
图像的spatial domain 和 frequency domain 图像压缩
Force buckle 575 Divide candy
微信红包封面小程序源码-后台独立版-带测评积分功能源码