Java custom class loader pit record

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

 

 

Tags: Java

Posted by mickfuzz on Wed, 18 May 2022 15:21:20 +0300