DynamicClassLoader.java
package net.minidev.asm;
/*
* Copyright 2011-2024 JSON-SMART authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.lang.reflect.Method;
/**
* Simple extension from ClassLoader overriding the loadClass(String name, boolean resolve) method
* and allowing to register new classes
*
* @author uriel
*/
class DynamicClassLoader extends ClassLoader {
DynamicClassLoader(ClassLoader parent) {
super(parent);
}
private static final String BEAN_AC = BeansAccess.class.getName();
/** Predefined define defineClass method signature (name, bytes, offset, length) */
private static final Class<?>[] DEF_CLASS_SIG =
new Class[] {String.class, byte[].class, int.class, int.class};
/**
* @param parent used to choose the ClassLoader
* @param clsName C
* @param clsData
* @return
*/
public static <T> Class<T> directLoad(Class<? extends T> parent, String clsName, byte[] clsData) {
DynamicClassLoader loader = new DynamicClassLoader(parent.getClassLoader());
@SuppressWarnings("unchecked")
Class<T> clzz = (Class<T>) loader.defineClass(clsName, clsData);
return clzz;
}
public static <T> T directInstance(Class<? extends T> parent, String clsName, byte[] clsData)
throws InstantiationException, IllegalAccessException {
Class<T> clzz = directLoad(parent, clsName, clsData);
return clzz.newInstance();
}
@Override
protected synchronized java.lang.Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
/*
* check class by fullname as String.
*/
if (name.equals(BEAN_AC)) return BeansAccess.class;
/*
* Use default class loader
*/
return super.loadClass(name, resolve);
}
/**
* Call defineClass into the parent classLoader using the method.setAccessible(boolean) hack
*
* @see ClassLoader#defineClass(String, byte[], int, int)
*/
Class<?> defineClass(String name, byte[] bytes) throws ClassFormatError {
try {
// Attempt to load the access class in the same loader, which makes
// protected and default access members accessible.
Method method = ClassLoader.class.getDeclaredMethod("defineClass", DEF_CLASS_SIG);
method.setAccessible(true);
return (Class<?>)
method.invoke(
getParent(),
new Object[] {name, bytes, Integer.valueOf(0), Integer.valueOf(bytes.length)});
} catch (Exception ignored) {
}
return defineClass(name, bytes, 0, bytes.length);
}
}