Detailed introduction to Java dynamic class loading and reloading
This article brings you a detailed introduction to Java dynamic class loading and reloading. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.
Classes can be loaded and reloaded at runtime in Java, although it is not as simple as we think. This article will explain when and how to load and reload classes in Java.
You can argue whether dynamically loading classes is part of Java reflection or part of Java core. Anyway, I put it in Java Reflection for lack of a better place to put it.
Class Loader
All classes in a Java program are loaded using some subclasses of java.lang.ClassLoader. Therefore, dynamically loaded classes must also use a subclass of java.lang.ClassLoader.
When a class is loaded, the classes it references will also be loaded. Class loading mode loads recursively until all required classes are loaded. This may not be all classes for the application. Unreferenced classes are not loaded until they are referenced.
Class loading hierarchy
Class loading in Java is organized into hierarchies. When you create a standalone ClassLoader, you must provide a parent ClassLoader. If a ClassLoader is asked to load a class, it will ask its parent ClassLoader to load it. If the parent class loader cannot find the class, the child class loader will try to load it itself.
Class loading
The steps for the class loader to load a class are as follows:
Check whether the class has been loaded
If the class is not loaded, request the parent class loader to load it
If the parent class loader cannot load the class, try to use the current class loader to load it
When you implement a class loader that can overload classes, you need to deviate a little from this sequence. The parent class loader should not be asked to load the class to be reloaded. More on that later.
Dynamic Class Loading
Dynamic loading of classes is very simple. All you need to do is get a ClassLoader and call its loadClass() method. An example is as follows:
public class MainClass { public static void main(String[] args){ ClassLoader classLoader = MainClass.class.getClassLoader(); try { Class aClass = classLoader.loadClass("com.jenkov.MyClass"); System.out.println("aClass.getName() = " + aClass.getName()); } catch (ClassNotFoundException e) { e.printStackTrace(); } }
Dynamic Class Reloading
Dynamic class reloading has some challenges. Java's built-in class loader always checks whether the class has been loaded before loading it. Therefore, it is not possible to reload a class using Java's built-in class loader. To reload a class you must implement your own ClassLoader subclass.
Even with custom subclasses of class loaders, there are challenges. All loaded classes need to be linked. This method is final and therefore cannot be overridden by your ClassLoader subclasses. The resolve() method does not allow a ClassLoader instance to link to a class twice. Therefore, whenever you need to reload a class, you must recreate an instance of the ClassLoader class. It's not impossible, but one has to know when to design the class to reload.
Class overloading code design
As mentioned above, the ClassLoader that loads the specified class cannot be used to reload this class. Therefore, a different ClassLoader must be used to load this class. However, this creates new problems.
Each class loaded in a Java program is identified by its fully qualified name (package name class name) and is loaded by a ClassLoader instance. This means that the class MyObject loaded by class loader A is different from the same class MyObject loaded by class loader B. The simulation code is as follows:
MyObject object = (MyObject) myClassReloadingFactory.newInstance("com.jenkov.MyObject");
Note how the class MyObject is referenced in the code as a variable of type object. This causes the MyObject class to be loaded by the class loader that already loaded the resident code for this class.
If the myClassReloadingFactory object factory uses a different class loader than the resident code to load MyObject, you cannot cast the reloaded Object type variable MyObject to the MyObject type. Because the two MyObjects are loaded by different class loaders, they are considered different classes, even though they have the same fully qualified name. Attempting to cast an object's class as a reference to another class will throw a ClassCastException.
It is possible to get around this limitation, but you have to change your code in two ways:
-
Use interface as variable type, and only reload the implementation class
Use superclass as variable type and only reload subclasses
Here is the sample code:
MyObjectInterface object = (MyObjectInterface) myClassReloadingFactory.newInstance("com.jenkov.MyObject");
MyObjectSuperclass object = (MyObjectSuperclass) myClassReloadingFactory.newInstance("com.jenkov.MyObject");
If the variable type is Interface or superclass, the above code will run normally, the interface or superclass will not be reloaded when the implementation or subclass is reloaded.
In order for the above code to run normally, you certainly need to implement your own class loader so that the interface or super class is loaded by its parent class. When your class loader is asked to load MyObject, it will also be asked to load the MyObjectInterface interface or MyObjectSuperclass class, because they are referenced internally by the MyObject class. Your class loader must delegate class loading to the same class loader that loaded the interface or superclass.
类加载器加载/重新加载示例
上文包含了很多内容。让我们看一下简单的示例。下面是一个简单的ClassLoader子类。注意它如何将类加载委托给它的父类,除了它想要重装的一个类之外。如果类加载被委派给了它的父类,它以后将不能被重新加载。记住,一个类只能被同一个ClassLoader实例加载。
如前所述,这只是一个示例,它显示了类加载器的行为的基本知识。这并不是一个你的类加载器的生产就绪的模板。你的类加载器可能并不仅限于一个类,可能是一个你想要重新加载的类的集合。此外,你也不能硬编码class path。
public class MyClassLoader extends ClassLoader{ public MyClassLoader(ClassLoader parent) { super(parent); } public Class loadClass(String name) throws ClassNotFoundException { if(!"reflection.MyObject".equals(name)) return super.loadClass(name); try { String url = "file:C:/data/projects/tutorials/web/WEB-INF/" + "classes/reflection/MyObject.class"; URL myUrl = new URL(url); URLConnection connection = myUrl.openConnection(); InputStream input = connection.getInputStream(); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int data = input.read(); while(data != -1){ buffer.write(data); data = input.read(); } input.close(); byte[] classData = buffer.toByteArray(); return defineClass("reflection.MyObject", classData, 0, classData.length); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } }
下面是使用MyClassLoader的示例:
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException { ClassLoader parentClassLoader = MyClassLoader.class.getClassLoader(); MyClassLoader classLoader = new MyClassLoader(parentClassLoader); Class myObjectClass = classLoader.loadClass("reflection.MyObject"); AnInterface2 object1 = (AnInterface2) myObjectClass.newInstance(); MyObjectSuperClass object2 = (MyObjectSuperClass) myObjectClass.newInstance(); //create new class loader so classes can be reloaded. classLoader = new MyClassLoader(parentClassLoader); myObjectClass = classLoader.loadClass("reflection.MyObject"); object1 = (AnInterface2) myObjectClass.newInstance(); object2 = (MyObjectSuperClass) myObjectClass.newInstance(); }
reflection.MyObject类是由自定义类加载器加载的。注意,它是如何继承一个超类、实现一个接口的。这只是为了这个例子。在你的代码中,只需要两个中的一个,继承超类或实现接口。
public class MyObject extends MyObjectSuperClass implements AnInterface2{ //... body of class ... override superclass methods // or implement interface methods }
The above is the detailed content of Detailed introduction to Java dynamic class loading and reloading. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



Guide to Perfect Number in Java. Here we discuss the Definition, How to check Perfect number in Java?, examples with code implementation.

Guide to Weka in Java. Here we discuss the Introduction, how to use weka java, the type of platform, and advantages with examples.

Guide to Smith Number in Java. Here we discuss the Definition, How to check smith number in Java? example with code implementation.

In this article, we have kept the most asked Java Spring Interview Questions with their detailed answers. So that you can crack the interview.

Java 8 introduces the Stream API, providing a powerful and expressive way to process data collections. However, a common question when using Stream is: How to break or return from a forEach operation? Traditional loops allow for early interruption or return, but Stream's forEach method does not directly support this method. This article will explain the reasons and explore alternative methods for implementing premature termination in Stream processing systems. Further reading: Java Stream API improvements Understand Stream forEach The forEach method is a terminal operation that performs one operation on each element in the Stream. Its design intention is

Guide to TimeStamp to Date in Java. Here we also discuss the introduction and how to convert timestamp to date in java along with examples.

Capsules are three-dimensional geometric figures, composed of a cylinder and a hemisphere at both ends. The volume of the capsule can be calculated by adding the volume of the cylinder and the volume of the hemisphere at both ends. This tutorial will discuss how to calculate the volume of a given capsule in Java using different methods. Capsule volume formula The formula for capsule volume is as follows: Capsule volume = Cylindrical volume Volume Two hemisphere volume in, r: The radius of the hemisphere. h: The height of the cylinder (excluding the hemisphere). Example 1 enter Radius = 5 units Height = 10 units Output Volume = 1570.8 cubic units explain Calculate volume using formula: Volume = π × r2 × h (4

Java is a popular programming language that can be learned by both beginners and experienced developers. This tutorial starts with basic concepts and progresses through advanced topics. After installing the Java Development Kit, you can practice programming by creating a simple "Hello, World!" program. After you understand the code, use the command prompt to compile and run the program, and "Hello, World!" will be output on the console. Learning Java starts your programming journey, and as your mastery deepens, you can create more complex applications.
