public static Method getClassMethod( String classInternalName, String methodName, String methodDesc) { checkArgNotNull(classInternalName, "classInternalName"); checkArgNotNull(methodName, "methodName"); checkArgNotNull(methodDesc, "methodDesc"); Class<?> clazz = getClassForInternalName(classInternalName); Type[] types = Type.getArgumentTypes(methodDesc); Class<?>[] argTypes = new Class<?>[types.length]; for (int i = 0; i < types.length; i++) { argTypes[i] = getClassForType(types[i]); } Class<?> current = clazz; while (true) { try { return current.getDeclaredMethod(methodName, argTypes); } catch (NoSuchMethodException e) { current = current.getSuperclass(); if (Object.class.equals(current)) { throw new RuntimeException( "Method '" + methodName + "' with descriptor '" + methodDesc + "' not found in '" + clazz + "\' or any superclass", e); } } } }
public static Constructor getClassConstructor(String classInternalName, String constructorDesc) { checkArgNotNull(classInternalName, "classInternalName"); checkArgNotNull(constructorDesc, "constructorDesc"); Class<?> clazz = getClassForInternalName(classInternalName); Type[] types = Type.getArgumentTypes(constructorDesc); Class<?>[] argTypes = new Class<?>[types.length]; for (int i = 0; i < types.length; i++) { argTypes[i] = getClassForType(types[i]); } try { return clazz.getDeclaredConstructor(argTypes); } catch (NoSuchMethodException e) { throw new RuntimeException( "Constructor with descriptor '" + constructorDesc + "' not found in '" + clazz, e); } }
public static Field getClassField(String classInternalName, String fieldName) { checkArgNotNull(classInternalName, "classInternalName"); checkArgNotNull(fieldName, "fieldName"); Class<?> clazz = getClassForInternalName(classInternalName); Class<?> current = clazz; while (true) { try { return current.getDeclaredField(fieldName); } catch (NoSuchFieldException e) { current = current.getSuperclass(); if (Object.class.equals(current)) { throw new RuntimeException( "Field '" + fieldName + "' not found in '" + clazz + "\' or any superclass", e); } } } }
/** * Returns the class with the given name if it has already been loaded by the given class loader. * Otherwise the method returns null. * * @param className the full name of the class to be loaded * @param classLoader the class loader to use * @return the class instance or null */ public static Class<?> findLoadedClass(String className, ClassLoader classLoader) { checkArgNotNull(className, "className"); checkArgNotNull(classLoader, "classLoader"); try { Class<?> classLoaderBaseClass = Class.forName("java.lang.ClassLoader"); Method findLoadedClassMethod = classLoaderBaseClass.getDeclaredMethod("findLoadedClass", String.class); // protected method invocation findLoadedClassMethod.setAccessible(true); try { return (Class<?>) findLoadedClassMethod.invoke(classLoader, className); } finally { findLoadedClassMethod.setAccessible(false); } } catch (Exception e) { throw new RuntimeException( "Could not determine whether class '" + className + "' has already been loaded", e); } }
/** * Loads the class defined with the given name and bytecode using the given class loader. Since * package and class idendity includes the ClassLoader instance used to load a class we use * reflection on the given class loader to define generated classes. If we used our own class * loader (in order to be able to access the protected "defineClass" method) we would likely still * be able to load generated classes, however, they would not have access to package-private * classes and members of their super classes. * * @param className the full name of the class to be loaded * @param code the bytecode of the class to load * @param classLoader the class loader to use * @return the class instance */ public static Class<?> loadClass(String className, byte[] code, ClassLoader classLoader) { checkArgNotNull(className, "className"); checkArgNotNull(code, "code"); checkArgNotNull(classLoader, "classLoader"); try { Class<?> classLoaderBaseClass = Class.forName("java.lang.ClassLoader"); Method defineClassMethod = classLoaderBaseClass.getDeclaredMethod( "defineClass", String.class, byte[].class, int.class, int.class); // protected method invocation defineClassMethod.setAccessible(true); try { return (Class<?>) defineClassMethod.invoke(classLoader, className, code, 0, code.length); } finally { defineClassMethod.setAccessible(false); } } catch (Exception e) { throw new RuntimeException("Could not load class '" + className + '\'', e); } }
public static ClassReader createClassReader(Class<?> clazz) throws IOException { checkArgNotNull(clazz, "clazz"); String classFilename = clazz.getName().replace('.', '/') + ".class"; InputStream inputStream = clazz.getClassLoader().getResourceAsStream(classFilename); return new ClassReader(inputStream); }
/** * Determines whether the class with the given descriptor is assignable to the given type. * * @param classInternalName the class descriptor * @param type the type * @return true if the class with the given descriptor is assignable to the given type */ public static boolean isAssignableTo(String classInternalName, Class<?> type) { checkArgNotNull(classInternalName, "classInternalName"); checkArgNotNull(type, "type"); return type.isAssignableFrom(getClassForInternalName(classInternalName)); }