I'm Shendi
Custom class loaders are needed to make it hotter these days
That is, let a class inherit ClassLoader
class SKClassLoader extends ClassLoader { }
Then you can use some protected modification methods of ClassLoader
For example, my most commonly used defineClass
- defineClass can convert bytes into classes
At the beginning, I directly used the defineClass to achieve more heat. Because a class loader object can only load classes once, I need to re create new objects every time I get the same class
The code is as follows, using some tools written by yourself
class SKClassLoader extends ClassLoader { public static Class<?> reloadClass(String clazz) throws ClassNotFoundException { if (clazz == null) return null; else { sk = new SKClassLoader(); clazz = "/".concat(clazz.replace('.', '/').concat(ShendiKitInfo.CLASS_SUFFIX)); byte[] classData = null; try (InputStream input = SKClassLoader.class.getResourceAsStream(clazz)) { classData = new byte[input.available()]; input.read(classData, 0, classData.length); } catch (IOException e) { Log.printErr("Error reloading specified class get: " + clazz + "---" + e.getMessage()); return null; } return sk.defineClass(null, classData, 0, classData.length); } } }
The general content is to read the corresponding class file into a byte stream, and then use defineClass to change the bytes into classes
At this time, it can be heated more
So I push ed the project to github
Then I found the problem when I used this class loader when writing web projects
Hot change can be done in ordinary java projects, but not in web projects
So I thought of the parent loading mechanism. I thought that the parent loader loaded the class, so the subclass retrieved the class loaded by the parent
Then I did a lot of operations and tested it many times (I'm still not proficient in using ClassLoader)
For example, directly use the loadClass method to load classes, and directly use findClass to load classes
A lot of mistakes were made during the period, and one after another
The most impressive is ClassNotDefFoundException
...
Later, the findClass method is implemented in the custom class loader by consulting
The code is as follows
@Override protected Class<?> findClass(String name) throws ClassNotFoundException { Class<?> c = findLoadedClass(name); if (c == null) { sk = new SKClassLoader(); name = "/".concat(name.replace('.', '/').concat(ShendiKitInfo.CLASS_SUFFIX)); byte[] classData = null; try (InputStream input = SKClassLoader.class.getResourceAsStream(name)) { classData = new byte[input.available()]; input.read(classData, 0, classData.length); } catch (IOException e) { Log.printErr("Error reloading specified class get: " + name + "---" + e.getMessage()); return null; } return sk.defineClass(null, classData, 0, classData.length); } return c; }
The specific content is to load first through findLoadedClass. If it is empty, it will be obtained through defineClass
Then I load the class through this method
Then test
...
There is no problem in ordinary Java projects, and the error occurs again in web projects
A permission exception or something
Later, we continued to consult and found the correct method of use
To load classes, the custom class loader needs to implement the findClass method, and the code is like that above
In the process of using, the loadClass method is used
Then test
There are no problems or errors in the code
But here comes the strange question
It is still impossible to perform hot change in web projects
Then, according to the parental loading mechanism, I output the obtained class and direct XX HashCode of class
Then it is found that the two are different. Yes, because they are loaded by two class loaders
So he did a lot of useless operations and gave up
...
Then I found that I had a wrong understanding of the defineClass method. This method defines the class directly through bytes and will not be affected by the parental mechanism, so I restored the code to the original state
Can web projects become more popular without entanglement
Finish work