in other words, java.lang.invoke.MethodHandles.Lookup.
.project
.settings
TestLog.xml
-
+*~
<p>-version 3.24
<ul>
+ <li>Java 11 supports.</li>
<li>JIRA JASSIST-267.</li>
<li>Github PR #218.</li>
</ul>
* the <code>getClassLoader()</code> method.
* If the program is running on some application
* server, the context class loader might be inappropriate to load the
- * class.
+ * class.</p>
*
* <p>This method is provided for convenience. If you need more
* complex functionality, you should write your own class loader.
*
- * <p><b>Warining:</b> A Class object returned by this method may not
+ * <p><b>Warining:</b>
+ * This method should not be used in Java 11 or later.
+ * Use {@link #toClass(CtClass,Class)}.
+ * </p>
+ *
+ * <p><b>Warining:</b>
+ * A Class object returned by this method may not
* work with a security manager or a signed jar file because a
- * protection domain is not specified.
+ * protection domain is not specified.</p>
*
- * @see #toClass(CtClass, java.lang.ClassLoader, ProtectionDomain)
+ * @see #toCalss(CtClass,Class)
+ * @see #toClass(CtClass,Class,java.lang.ClassLoader,ProtectionDomain)
* @see #getClassLoader()
*/
public Class toClass(CtClass clazz) throws CannotCompileException {
/**
* Converts the class to a <code>java.lang.Class</code> object.
* Do not override this method any more at a subclass because
- * <code>toClass(CtClass)</code> never calls this method.
+ * {@link #toClass(CtClass)} will never calls this method.
*
* <p><b>Warining:</b> A Class object returned by this method may not
* work with a security manager or a signed jar file because a
* protection domain is not specified.
*
- * @deprecated Replaced by {@link #toClass(CtClass,ClassLoader,ProtectionDomain)}.
+ * @deprecated Replaced by {@link #toClass(CtClass,Class,ClassLoader,ProtectionDomain)}.
* A subclass of <code>ClassPool</code> that has been
* overriding this method should be modified. It should override
- * {@link #toClass(CtClass,ClassLoader,ProtectionDomain)}.
+ * {@link #toClass(CtClass,Class,ClassLoader,ProtectionDomain)}.
*/
public Class toClass(CtClass ct, ClassLoader loader)
throws CannotCompileException
{
- return toClass(ct, loader, null);
+ return toClass(ct, null, loader, null);
}
/**
* loaded by the given class loader to construct a
* <code>java.lang.Class</code> object. Since a private method
* on the class loader is invoked through the reflection API,
- * the caller must have permissions to do that.
+ * the caller must have permissions to do that.</p>
*
* <p>An easy way to obtain <code>ProtectionDomain</code> object is
* to call <code>getProtectionDomain()</code>
* class belongs to.
*
* <p>This method is provided for convenience. If you need more
- * complex functionality, you should write your own class loader.
+ * complex functionality, you should write your own class loader.</p>
*
+ * @param ct the class converted into {@code java.lang.Class}.
* @param loader the class loader used to load this class.
* For example, the loader returned by
* <code>getClassLoader()</code> can be used
*
* @see #getClassLoader()
* @since 3.3
+ * @deprecated Replaced by {@link #toClass(CtClass,Class,ClassLoader,ProtectionDomain)}.
*/
public Class toClass(CtClass ct, ClassLoader loader, ProtectionDomain domain)
throws CannotCompileException
+ {
+ return toClass(ct, null, loader, domain);
+ }
+
+ /**
+ * Converts the class to a <code>java.lang.Class</code> object.
+ * Once this method is called, further modifications are not allowed
+ * any more.
+ *
+ * <p>This method is available in Java 9 or later.
+ * It loads the class
+ * by using {@code java.lang.invoke.MethodHandles} with {@code neighbor}.
+ * </p>
+ *
+ * @param ct the class converted into {@code java.lang.Class}.
+ * @param neighbor a class belonging to the same package that
+ * the converted class belongs to.
+ * @since 3.24
+ */
+ public Class<?> toClass(CtClass ct, Class<?> neighbor)
+ throws CannotCompileException
+ {
+ try {
+ return javassist.util.proxy.DefineClassHelper.toClass(neighbor,
+ ct.toBytecode());
+ }
+ catch (IOException e) {
+ throw new CannotCompileException(e);
+ }
+ }
+
+ /**
+ * Converts the class to a <code>java.lang.Class</code> object.
+ * Once this method is called, further modifications are not allowed
+ * any more.
+ *
+ * <p>This method is available in Java 9 or later.
+ * It loads the class
+ * by using the given {@code java.lang.invoke.MethodHandles.Lookup}.
+ * </p>
+ *
+ * @param ct the class converted into {@code java.lang.Class}.
+ * @since 3.24
+ */
+ public Class<?> toClass(CtClass ct,
+ java.lang.invoke.MethodHandles.Lookup lookup)
+ throws CannotCompileException
+ {
+ try {
+ return javassist.util.proxy.DefineClassHelper.toClass(lookup,
+ ct.toBytecode());
+ }
+ catch (IOException e) {
+ throw new CannotCompileException(e);
+ }
+ }
+
+ /**
+ * Converts the class to a <code>java.lang.Class</code> object.
+ * Once this method is called, further modifications are not allowed
+ * any more.
+ *
+ * <p>When the JVM is Java 11 or later, this method loads the class
+ * by using {@code java.lang.invoke.MethodHandles} with {@code neighbor}.
+ * The other arguments {@code loader} and {@code domain} are not used;
+ * so they can be null.
+ * </p>
+ *
+ * <p>Otherwise, or when {@code neighbor} is null,
+ * the class file represented by the given <code>CtClass</code> is
+ * loaded by the given class loader to construct a
+ * <code>java.lang.Class</code> object. Since a private method
+ * on the class loader is invoked through the reflection API,
+ * the caller must have permissions to do that.
+ *
+ * <p>An easy way to obtain <code>ProtectionDomain</code> object is
+ * to call <code>getProtectionDomain()</code>
+ * in <code>java.lang.Class</code>. It returns the domain that the
+ * class belongs to.
+ *
+ * <p>If your program is for only Java 9 or later, don't use this method.
+ * Use {@link #toClass(CtClass,Class)} or
+ * {@link #toClass(CtClass)CtClass,java.lang.invoke.MethodHandles.Lookup)}.
+ * </p>
+ *
+ * @param ct the class converted into {@code java.lang.Class}.
+ * @param neighbor a class belonging to the same package that
+ * the converted class belongs to.
+ * It can be null.
+ * @param loader the class loader used to load this class.
+ * For example, the loader returned by
+ * <code>getClassLoader()</code> can be used
+ * for this parameter.
+ * @param domain the protection domain for the class.
+ * If it is null, the default domain created
+ * by <code>java.lang.ClassLoader</code> is used.
+ *
+ * @see #getClassLoader()
+ * @since 3.24
+ */
+ public Class toClass(CtClass ct, Class<?> neighbor, ClassLoader loader,
+ ProtectionDomain domain)
+ throws CannotCompileException
{
try {
return javassist.util.proxy.DefineClassHelper.toClass(ct.getName(),
- loader, domain, ct.toBytecode());
+ neighbor, loader, domain, ct.toBytecode());
}
catch (IOException e) {
throw new CannotCompileException(e);
* work with a security manager or a signed jar file because a
* protection domain is not specified.
*
- * @see #toClass(java.lang.ClassLoader,ProtectionDomain)
+ * @see #toClass(java.lang.invoke.MethodHandles.Lookup)
+ * @see #toClass(Class)
* @see ClassPool#toClass(CtClass)
*/
public Class<?> toClass() throws CannotCompileException {
return getClassPool().toClass(this);
}
+ /**
+ * Converts this class to a <code>java.lang.Class</code> object.
+ * Once this method is called, further modifications are not
+ * allowed any more.
+ *
+ * <p>This method is provided for convenience. If you need more
+ * complex functionality, you should write your own class loader.
+ *
+ * <p>Note: this method calls <code>toClass()</code>
+ * in <code>ClassPool</code>.
+ *
+ * <p><b>Warining:</b> A Class object returned by this method may not
+ * work with a security manager or a signed jar file because a
+ * protection domain is not specified.
+ *
+ * @param neighbor A class belonging to the same package that this
+ * class belongs to. It is used to load the class.
+ * @see ClassPool#toClass(CtClass,Class)
+ * @since 3.24
+ */
+ public Class<?> toClass(Class<?> neighbor) throws CannotCompileException
+ {
+ return getClassPool().toClass(this, neighbor);
+ }
+
+ /**
+ * Converts this class to a <code>java.lang.Class</code> object.
+ * Once this method is called, further modifications are not
+ * allowed any more.
+ *
+ * <p>This method is provided for convenience. If you need more
+ * complex functionality, you should write your own class loader.
+ *
+ * <p>Note: this method calls <code>toClass()</code>
+ * in <code>ClassPool</code>.
+ *
+ * <p><b>Warining:</b> A Class object returned by this method may not
+ * work with a security manager or a signed jar file because a
+ * protection domain is not specified.
+ *
+ * @param lookup used when loading the class. It has to have
+ * an access right to define a new class.
+ * @see ClassPool#toClass(CtClass,java.lang.invoke.MethodHandles.Lookup)
+ * @since 3.24
+ */
+ public Class<?> toClass(java.lang.invoke.MethodHandles.Lookup lookup)
+ throws CannotCompileException
+ {
+ return getClassPool().toClass(this, lookup);
+ }
+
/**
* Converts this class to a <code>java.lang.Class</code> object.
* Once this method is called, further modifications are not allowed
if (loader == null)
loader = cp.getClassLoader();
- return cp.toClass(this, loader, domain);
+ return cp.toClass(this, null, loader, domain);
}
/**
public final Class<?> toClass(ClassLoader loader)
throws CannotCompileException
{
- return getClassPool().toClass(this, loader);
+ return getClassPool().toClass(this, null, loader, null);
}
/**
* @see ClassPool#doPruning
*
* @see #toBytecode()
- * @see #toClass()
+ * @see #toClass(Class)
* @see #writeFile()
* @see #instrument(CodeConverter)
* @see #instrument(ExprEditor)
package javassist;
+import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.security.ProtectionDomain;
import java.util.Arrays;
-import java.util.Hashtable;
+import java.util.HashMap;
import java.util.Vector;
import javassist.bytecode.ClassFile;
* @see javassist.Translator
*/
public class Loader extends ClassLoader {
- private Hashtable<String,ClassLoader> notDefinedHere; // must be atomic.
+
+ /**
+ * A simpler class loader.
+ * This is a class loader that exposes the protected {@code defineClass()} method
+ * declared in {@code java.lang.ClassLoader}. It provides a method similar to
+ * {@code CtClass#toClass()}.
+ *
+ * <p>When loading a class, this class loader delegates the work to the
+ * parent class loader unless the loaded classes are explicitly given
+ * by {@link #invokeDefineClass(CtClass)}.
+ * Note that a class {@code Foo} loaded by this class loader is
+ * different from the class with the same name {@code Foo} but loaded by
+ * another class loader. This is Java's naming rule.
+ * </p>
+ *
+ * @since 3.24
+ */
+ public static class Simple extends ClassLoader {
+ /**
+ * Constructs a class loader.
+ */
+ public Simple() {}
+
+ /**
+ * Constructs a class loader.
+ * @param parent the parent class loader.
+ */
+ public Simple(ClassLoader parent) {
+ super(parent);
+ }
+
+ /**
+ * Invokes the protected {@code defineClass()} in {@code ClassLoader}.
+ * It converts the given {@link CtClass} object into a {@code java.lang.Class} object.
+ */
+ public Class<?> invokeDefineClass(CtClass cc) throws IOException, CannotCompileException {
+ byte[] code = cc.toBytecode();
+ return defineClass(cc.getName(), code, 0, code.length);
+ }
+ }
+
+ private HashMap<String,ClassLoader> notDefinedHere; // must be atomic.
private Vector<String> notDefinedPackages; // must be atomic.
private ClassPool source;
private Translator translator;
}
private void init(ClassPool cp) {
- notDefinedHere = new Hashtable<String,ClassLoader>();
+ notDefinedHere = new HashMap<String,ClassLoader>();
notDefinedPackages = new Vector<String>();
source = cp;
translator = null;
public class DefineClassHelper {
private static abstract class Helper {
- abstract Class<?> defineClass(String name, byte[] b, int off, int len,
+ abstract Class<?> defineClass(String name, byte[] b, int off, int len, Class<?> neighbor,
ClassLoader loader, ProtectionDomain protectionDomain)
- throws ClassFormatError;
+ throws ClassFormatError, CannotCompileException;
+ }
+
+ private static class Java11 extends JavaOther {
+ Class<?> defineClass(String name, byte[] bcode, int off, int len, Class<?> neighbor,
+ ClassLoader loader, ProtectionDomain protectionDomain)
+ throws ClassFormatError, CannotCompileException
+ {
+ if (neighbor != null)
+ return toClass(neighbor, bcode);
+ else {
+ // Lookup#defineClass() is not available. So fallback to invoking defineClass on
+ // ClassLoader, which causes a warning message.
+ return super.defineClass(name, bcode, off, len, neighbor, loader, protectionDomain);
+ }
+ }
}
private static class Java9 extends Helper {
}
@Override
- Class<?> defineClass(String name, byte[] b, int off, int len,
+ Class<?> defineClass(String name, byte[] b, int off, int len, Class<?> neighbor,
ClassLoader loader, ProtectionDomain protectionDomain)
throws ClassFormatError
{
}
@Override
- Class<?> defineClass(String name, byte[] b, int off, int len,
+ Class<?> defineClass(String name, byte[] b, int off, int len, Class<?> neighbor,
ClassLoader loader, ProtectionDomain protectionDomain)
throws ClassFormatError
{
}
@Override
- Class<?> defineClass(String name, byte[] b, int off, int len,
+ Class<?> defineClass(String name, byte[] b, int off, int len, Class<?> neighbor,
ClassLoader loader, ProtectionDomain protectionDomain)
- throws ClassFormatError
+ throws ClassFormatError, CannotCompileException
{
- if (stack.getCallerClass() != DefineClassHelper.class)
+ Class<?> klass = stack.getCallerClass();
+ if (klass != DefineClassHelper.class && klass != this.getClass())
throw new IllegalAccessError("Access denied for caller.");
try {
SecurityActions.setAccessible(defineClass, true);
} catch (Throwable e) {
if (e instanceof ClassFormatError) throw (ClassFormatError) e;
if (e instanceof RuntimeException) throw (RuntimeException) e;
- throw new ClassFormatError(e.getMessage());
+ throw new CannotCompileException(e);
}
finally {
SecurityActions.setAccessible(defineClass, false);
// Java 11+ removed sun.misc.Unsafe.defineClass, so we fallback to invoking defineClass on
// ClassLoader until we have an implementation that uses MethodHandles.Lookup.defineClass
private static final Helper privileged = ClassFile.MAJOR_VERSION > ClassFile.JAVA_10
- ? new JavaOther()
+ ? new Java11()
: ClassFile.MAJOR_VERSION >= ClassFile.JAVA_9
? new Java9()
: ClassFile.MAJOR_VERSION >= ClassFile.JAVA_7 ? new Java7() : new JavaOther();
/**
* Loads a class file by a given class loader.
*
- * <p>This first tries to use {@code sun.misc.Unsafe} to load a class.
+ * <p>This first tries to use {@code java.lang.invoke.MethodHandle} to load a class.
+ * Otherwise, or if {@code neighbor} is null,
+ * this tries to use {@code sun.misc.Unsafe} to load a class.
* Then it tries to use a {@code protected} method in {@code java.lang.ClassLoader}
* via {@code PrivilegedAction}. Since the latter approach is not available
* any longer by default in Java 9 or later, the JVM argument
* should be used instead.
* </p>
*
+ * @param className the name of the loaded class.
+ * @param neighbor the class contained in the same package as the loaded class.
+ * @param loader the class loader. It can be null if {@code neighbor} is not null
+ * and the JVM is Java 11 or later.
* @param domain if it is null, a default domain is used.
+ * @parma bcode the bytecode for the loaded class.
* @since 3.22
*/
- public static Class<?> toClass(String className, ClassLoader loader,
+ public static Class<?> toClass(String className, Class<?> neighbor, ClassLoader loader,
ProtectionDomain domain, byte[] bcode)
throws CannotCompileException
{
try {
- return privileged.defineClass(className, bcode, 0, bcode.length, loader, domain);
+ return privileged.defineClass(className, bcode, 0, bcode.length,
+ neighbor, loader, domain);
}
catch (RuntimeException e) {
throw e;
}
+ catch (CannotCompileException e) {
+ throw e;
+ }
catch (ClassFormatError e) {
Throwable t = e.getCause();
throw new CannotCompileException(t == null ? e : t);
}
}
+
+ /**
+ * Loads a class file by {@code java.lang.invoke.MethodHandles.Lookup}.
+ * It is obtained by using {@code neighbor}.
+ *
+ * @param neighbor a class belonging to the same package that the loaded
+ * class belogns to.
+ * @param bcode the bytecode.
+ * @since 3.24
+ */
+ public static Class<?> toClass(Class<?> neighbor, byte[] bcode)
+ throws CannotCompileException
+ {
+ try {
+ Lookup lookup = MethodHandles.lookup();
+ Lookup prvlookup = MethodHandles.privateLookupIn(neighbor, lookup);
+ return prvlookup.defineClass(bcode);
+ } catch (IllegalAccessException | IllegalArgumentException e) {
+ throw new CannotCompileException(e.getMessage() + ": " + neighbor.getName()
+ + " has no permission to define the class");
+ }
+ }
+
+ /**
+ * Loads a class file by {@code java.lang.invoke.MethodHandles.Lookup}.
+ * It can be obtained by {@code MethodHandles.lookup()} called from
+ * somewhere in the package that the loaded class belongs to.
+ *
+ * @param bcode the bytecode.
+ * @since 3.24
+ */
+ public static Class<?> toClass(Lookup lookup, byte[] bcode)
+ throws CannotCompileException
+ {
+ try {
+ return lookup.defineClass(bcode);
+ } catch (IllegalAccessException | IllegalArgumentException e) {
+ throw new CannotCompileException(e.getMessage());
+ }
+ }
+
/**
* Loads a class file by {@code java.lang.invoke.MethodHandles.Lookup}.
*
* This method uses a default protection domain for the class
* but it may not work with a security manager or a signed jar file.
*
- * @see #toClass(ClassFile,ClassLoader,ProtectionDomain)
+ * @see #toClass(ClassFile,Class,ClassLoader,ProtectionDomain)
+ * @deprecated
*/
public static Class<?> toClass(ClassFile cf, ClassLoader loader)
throws CannotCompileException
{
- return toClass(cf, loader, null);
+ return toClass(cf, null, loader, null);
}
/**
* Loads a class file by a given class loader.
*
+ * @param neighbor a class belonging to the same package that
+ * the loaded class belongs to.
+ * It can be null.
+ * @param loader The class loader. It can be null if {@code neighbor}
+ * is not null.
* @param domain if it is null, a default domain is used.
* @since 3.3
*/
- public static Class<?> toClass(ClassFile cf, ClassLoader loader, ProtectionDomain domain)
+ public static Class<?> toClass(ClassFile cf, Class<?> neighbor,
+ ClassLoader loader, ProtectionDomain domain)
throws CannotCompileException
{
try {
byte[] b = toBytecode(cf);
if (ProxyFactory.onlyPublicMethods)
return DefineClassHelper.toPublicClass(cf.getName(), b);
- return DefineClassHelper.toClass(cf.getName(), loader, domain, b);
+ else
+ return DefineClassHelper.toClass(cf.getName(), neighbor,
+ loader, domain, b);
}
catch (IOException e) {
throw new CannotCompileException(e);
*
* <p>The default value is {@code false}.</p>
*
- * @see DefineClassHelper#toClass(String, ClassLoader, ProtectionDomain, byte[])
+ * @see DefineClassHelper#toClass(String, Class<?>, ClassLoader, ProtectionDomain, byte[])
* @since 3.22
*/
public static boolean onlyPublicMethods = false;
if (writeDirectory != null)
FactoryHelper.writeFile(cf, writeDirectory);
- thisClass = FactoryHelper.toClass(cf, cl, getDomain());
+ thisClass = FactoryHelper.toClass(cf, getClassInTheSamePackage(), cl, getDomain());
setField(FILTER_SIGNATURE_FIELD, signature);
// legacy behaviour : we only set the default interceptor static field if we are not using the cache
if (!factoryUseCache) {
}
+ /**
+ * Obtains a class belonging to the same package that the created
+ * proxy class belongs to. It is used to obtain an appropriate
+ * {@code java.lang.invoke.MethodHandles.Lookup}.
+ */
+ private Class<?> getClassInTheSamePackage() {
+ if (superClass != null && superClass != OBJECT_TYPE)
+ return superClass;
+ else if (interfaces != null && interfaces.length > 0)
+ return interfaces[0];
+ else
+ return this.getClass(); // maybe wrong?
+ }
+
private void setField(String fieldName, Object value) {
if (thisClass != null && value != null)
try {
--- /dev/null
+/*
+ * This is used as a capability for running CtClass#toClass().
+ */
+public class DefineClassCapability {
+}
package javassist;
import junit.framework.*;
+import test1.DefineClassCapability;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
ctInterface.stopPruning(true);
ctInterface.writeFile();
- ctInterface.toClass();
- targetCtClass.toClass();
+ ctInterface.toClass(DefineClassCapability.class);
+ targetCtClass.toClass(DefineClassCapability.class);
}
public void testDispatch() throws Exception {
suite.addTestSuite(javassist.SetterTest.class);
suite.addTestSuite(javassist.bytecode.InsertGap0.class);
suite.addTestSuite(javassist.tools.reflect.LoaderTest.class);
+ suite.addTestSuite(javassist.tools.CallbackTest.class);
suite.addTestSuite(testproxy.ProxyTester.class);
suite.addTestSuite(testproxy.ProxyFactoryPerformanceTest.class); // remove?
suite.addTestSuite(javassist.proxyfactory.ProxyFactoryTest.class);
import java.lang.reflect.Method;
import javassist.expr.*;
+import test2.DefineClassCapability;
@SuppressWarnings({"rawtypes","unused"})
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public void testToClass() throws Exception {
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.makeClass("test2.ToClassTest");
- Class c = cc.toClass();
+ Class c = cc.toClass(DefineClassCapability.class);
assertEquals(getClass().getClassLoader(), c.getClassLoader());
}
System.out.println("Num Annotation : " +ans.length);
// c.debugWriteFile();
- Class newclass = c.toClass();
+ Class newclass = c.toClass(DefineClassCapability.class);
java.lang.annotation.Annotation[] anns = newclass.getAnnotations();
System.out.println("Num NewClass Annotation : " +anns.length);
assertEquals(ans.length, anns.length);
CtMethod m2 = cc2.getDeclaredMethod("getX");
copyAnnotations(m1, m2);
cc2.getClassFile();
- Class clazz = cc2.toClass();
+ Class clazz = cc2.toClass(DefineClassCapability.class);
java.lang.reflect.Method m = clazz.getDeclaredMethod("getX", new Class[0]);
assertEquals(1, m.getAnnotations().length);
test3.VisibleAnno a = m.getAnnotation(test3.VisibleAnno.class);
cc.addField(fobj, CtField.Initializer.constant("bar"));
cc.writeFile();
- Class clazz = cc.toClass();
+ Class clazz = cc.toClass(DefineClassCapability.class);
assertEquals(2L, clazz.getField("j").getLong(null));
assertEquals(3, clazz.getField("i").getInt(null));
assertEquals(4, clazz.getField("s").getShort(null));
sb.append("}");
ctc.addMethod(CtNewMethod.make(sb.toString(), ctc));
ctc.debugWriteFile();
- ctc.toClass().getConstructor().newInstance();
+ ctc.toClass(DefineClassCapability.class).getConstructor().newInstance();
}
// JIRA-83
addDeadCode(newClass, "public boolean evaluate7(){ return !true; }");
newClass.debugWriteFile();
- Class<?> cClass = newClass.toClass();
+ Class<?> cClass = newClass.toClass(test4.DefineClassCapability.class);
Object o = cClass.getConstructor().newInstance();
java.lang.reflect.Method m = cClass.getMethod("evaluate");
m.invoke(o);
attr.setAnnotation(a);
m.getMethodInfo().addAttribute(attr);
cc.writeFile();
+ anno.toClass(test4.DefineClassCapability.class);
Class<?> rc = ((java.lang.annotation.Annotation)m.getAnnotations()[0]).annotationType();
assertEquals(anno.getName(), rc.getName());
}
"}");
System.out.println(src);
badClass.addMethod(CtMethod.make(src, badClass));
- Class clazzz = badClass.toClass();
+ Class clazzz = badClass.toClass(Class.forName("DefineClassCapability"));
Object obj = clazzz.getConstructor().newInstance(); // <-- falls here
}
public void testNestHostAttributeCopy() throws Exception {
CtClass cc = sloader.get("test5.NestHost2$Foo");
cc.getClassFile().compact();
- cc.toClass();
+ cc.toClass(test5.DefineClassCapability.class);
}
}
-package javassist;\r
-import java.lang.reflect.Method;\r
-\r
-import junit.framework.TestCase;\r
-\r
-@SuppressWarnings({"rawtypes","unchecked"})\r
-public class SetterTest extends TestCase {\r
-\r
- ClassPool pool;\r
-\r
- public SetterTest(String name) {\r
- super(name);\r
- }\r
-\r
- protected void setUp() throws Exception {\r
- super.setUp();\r
- pool = ClassPool.getDefault();\r
- }\r
-\r
- /**\r
- * Tests a getter only on a field without a Modifier.\r
- * \r
- * @throws Exception\r
- */\r
- public void testFieldGetter() throws Exception {\r
- CtClass clazz = pool.makeClass("HasFieldGetter");\r
- clazz.setSuperclass(pool.get("java.lang.Object"));\r
- CtField field = new CtField(CtClass.booleanType, "broken", clazz);\r
- clazz.addField(field, "true");\r
- clazz.addMethod(CtNewMethod.getter("isBroken", field));\r
- Class _class = clazz.toClass();\r
-\r
- Object object = _class.getConstructor().newInstance();\r
- check(_class, object, true);\r
- }\r
-\r
- /**\r
- * Tests a getter and a setter on a field without a Modifier.\r
- * \r
- * @throws Exception\r
- */\r
- public void testFieldGetterSetter() throws Exception {\r
- CtClass clazz = pool.makeClass("HasFieldGetterSetter");\r
- clazz.setSuperclass(pool.get("java.lang.Object"));\r
- CtField field = new CtField(CtClass.booleanType, "broken", clazz);\r
- clazz.addField(field, "true");\r
- clazz.addMethod(CtNewMethod.getter("isBroken", field));\r
- clazz.addMethod(CtNewMethod.setter("setBroken", field));\r
- Class _class = clazz.toClass();\r
-\r
- Object object = _class.getConstructor().newInstance();\r
-\r
- set(_class, object, false);\r
- check(_class, object, false);\r
- }\r
-\r
- /**\r
- * Tests a getter only on a field with Modifier.STATIC.\r
- * \r
- * @throws Exception\r
- */\r
- public void testStaticFieldGetter() throws Exception {\r
- CtClass clazz = pool.makeClass("HasStaticFieldGetter");\r
- clazz.setSuperclass(pool.get("java.lang.Object"));\r
- CtField field = new CtField(CtClass.booleanType, "broken", clazz);\r
- field.setModifiers(Modifier.STATIC);\r
- clazz.addField(field, "true");\r
- clazz.addMethod(CtNewMethod.getter("isBroken", field));\r
- Class _class = clazz.toClass();\r
-\r
- Object object = _class.getConstructor().newInstance();\r
- check(_class, object, true);\r
- }\r
-\r
- /**\r
- * Tests a getter and setter on a field with Modifier.STATIC.\r
- * \r
- * @throws Exception\r
- */\r
- public void testStaticFieldGetterSetter() throws Exception {\r
- CtClass clazz = pool.makeClass("HasStaticFieldGetterSetter");\r
- clazz.setSuperclass(pool.get("java.lang.Object"));\r
- CtField field = new CtField(CtClass.booleanType, "broken", clazz);\r
- field.setModifiers(Modifier.STATIC);\r
- clazz.addField(field, "true");\r
- clazz.addMethod(CtNewMethod.getter("isBroken", field));\r
- clazz.addMethod(CtNewMethod.setter("setBroken", field));\r
- Class _class = clazz.toClass();\r
-\r
- Object object = _class.getConstructor().newInstance();\r
-\r
- set(_class, object, false);\r
- check(_class, object, false);\r
- }\r
-\r
- private void check(Class _class, Object object, boolean shouldBe)\r
- throws Exception\r
- {\r
- Method method = _class.getMethod("isBroken", new Class[] {});\r
- Boolean result = (Boolean) method.invoke(object, new Object[] {});\r
- assertEquals("boolean is wrong value",\r
- shouldBe, result.booleanValue());\r
- }\r
-\r
- private void set(Class _class, Object object, boolean willBe)\r
- throws Exception\r
- {\r
- Method method = _class.getMethod("setBroken",\r
- new Class[] {Boolean.TYPE});\r
- method.invoke(object, new Object[] { Boolean.valueOf(willBe)});\r
- }\r
-}\r
+package javassist;
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings({"rawtypes","unchecked"})
+public class SetterTest extends TestCase {
+
+ ClassPool pool;
+ Class<?> capability;
+
+ public SetterTest(String name) {
+ super(name);
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ pool = ClassPool.getDefault();
+ capability = Class.forName("DefineClassCapability");
+ }
+
+ /**
+ * Tests a getter only on a field without a Modifier.
+ *
+ * @throws Exception
+ */
+ public void testFieldGetter() throws Exception {
+ CtClass clazz = pool.makeClass("HasFieldGetter");
+ clazz.setSuperclass(pool.get("java.lang.Object"));
+ CtField field = new CtField(CtClass.booleanType, "broken", clazz);
+ clazz.addField(field, "true");
+ clazz.addMethod(CtNewMethod.getter("isBroken", field));
+ Class _class = clazz.toClass(capability);
+
+ Object object = _class.getConstructor().newInstance();
+ check(_class, object, true);
+ }
+
+ /**
+ * Tests a getter and a setter on a field without a Modifier.
+ *
+ * @throws Exception
+ */
+ public void testFieldGetterSetter() throws Exception {
+ CtClass clazz = pool.makeClass("HasFieldGetterSetter");
+ clazz.setSuperclass(pool.get("java.lang.Object"));
+ CtField field = new CtField(CtClass.booleanType, "broken", clazz);
+ clazz.addField(field, "true");
+ clazz.addMethod(CtNewMethod.getter("isBroken", field));
+ clazz.addMethod(CtNewMethod.setter("setBroken", field));
+ Class _class = clazz.toClass(capability);
+
+ Object object = _class.getConstructor().newInstance();
+
+ set(_class, object, false);
+ check(_class, object, false);
+ }
+
+ /**
+ * Tests a getter only on a field with Modifier.STATIC.
+ *
+ * @throws Exception
+ */
+ public void testStaticFieldGetter() throws Exception {
+ CtClass clazz = pool.makeClass("HasStaticFieldGetter");
+ clazz.setSuperclass(pool.get("java.lang.Object"));
+ CtField field = new CtField(CtClass.booleanType, "broken", clazz);
+ field.setModifiers(Modifier.STATIC);
+ clazz.addField(field, "true");
+ clazz.addMethod(CtNewMethod.getter("isBroken", field));
+ Class _class = clazz.toClass(capability);
+
+ Object object = _class.getConstructor().newInstance();
+ check(_class, object, true);
+ }
+
+ /**
+ * Tests a getter and setter on a field with Modifier.STATIC.
+ *
+ * @throws Exception
+ */
+ public void testStaticFieldGetterSetter() throws Exception {
+ CtClass clazz = pool.makeClass("HasStaticFieldGetterSetter");
+ clazz.setSuperclass(pool.get("java.lang.Object"));
+ CtField field = new CtField(CtClass.booleanType, "broken", clazz);
+ field.setModifiers(Modifier.STATIC);
+ clazz.addField(field, "true");
+ clazz.addMethod(CtNewMethod.getter("isBroken", field));
+ clazz.addMethod(CtNewMethod.setter("setBroken", field));
+ Class _class = clazz.toClass(capability);
+
+ Object object = _class.getConstructor().newInstance();
+
+ set(_class, object, false);
+ check(_class, object, false);
+ }
+
+ private void check(Class _class, Object object, boolean shouldBe)
+ throws Exception
+ {
+ Method method = _class.getMethod("isBroken", new Class[] {});
+ Boolean result = (Boolean) method.invoke(object, new Object[] {});
+ assertEquals("boolean is wrong value",
+ shouldBe, result.booleanValue());
+ }
+
+ private void set(Class _class, Object object, boolean willBe)
+ throws Exception
+ {
+ Method method = _class.getMethod("setBroken",
+ new Class[] {Boolean.TYPE});
+ method.invoke(object, new Object[] { Boolean.valueOf(willBe)});
+ }
+}
cc.addField(new CtField(CtClass.intType, "i", cc), "++counter");
boolean p = cc.stopPruning(true);
cc.writeFile();
- Class c = cc.toClass();
+ Class c = cc.toClass(ClassFile.class);
cc.stopPruning(p);
Object obj = c.getConstructor().newInstance();
cc.addField(new CtField(CtClass.intType, "i", cc), "++counter");
boolean p = cc.stopPruning(true);
cc.writeFile();
- Class c = cc.toClass();
+ Class c = cc.toClass(ClassFile.class);
cc.stopPruning(p);
Object obj = c.getConstructor().newInstance();
import javassist.*;
import junit.framework.TestCase;
import test.javassist.tools.DummyClass;
+import test.javassist.tools.DefineClassCapability;
import static javassist.tools.Callback.*;
});
// Change class and invoke method;
- classToChange.toClass();
+ classToChange.toClass(DefineClassCapability.class);
new DummyClass().dummyMethod();
}
}
--- /dev/null
+package test.javassist;
+
+/*
+ * This is used as a capability for running CtClass#toClass().
+ */
+public class DefineClassCapability {
+}
package test.javassist.convert;
-import java.net.URL;
-import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Map;
import junit.framework.TestCase;
public class ArrayAccessReplaceTest extends TestCase {
- private static SimpleInterface simple;
+ private static SimpleInterface simple = null;
public void setUp() throws Exception {
ClassPool pool = new ClassPool(true);
converter.replaceArrayAccess(echoClass, new CodeConverter.DefaultArrayAccessReplacementMethodNames());
simpleClass.instrument(converter);
//simpleClass.writeFile("/tmp");
- simple = (SimpleInterface) simpleClass.toClass(new URLClassLoader(new URL[0], getClass().getClassLoader()), Class.class.getProtectionDomain()).getConstructor().newInstance();
+
+ simple = (SimpleInterface)new javassist.Loader.Simple().invokeDefineClass(simpleClass)
+ .getConstructor().newInstance();
}
public void testComplex() throws Exception {
CodeConverter converter = new CodeConverter();
converter.replaceArrayAccess(clazz, new CodeConverter.DefaultArrayAccessReplacementMethodNames());
clazz.instrument(converter);
- ComplexInterface instance = (ComplexInterface) clazz.toClass(new URLClassLoader(new URL[0], getClass().getClassLoader()), Class.class.getProtectionDomain()).getConstructor().newInstance();
+ ComplexInterface instance
+ = (ComplexInterface)new javassist.Loader.Simple().invokeDefineClass(clazz)
+ .getConstructor().newInstance();
assertEquals(Integer.valueOf(5), instance.complexRead(4));
}
// now create a proxyfactory and use it to create a proxy
ProxyFactory factory = new ProxyFactory();
- Class javaTargetClass = classPool.toClass(ctTargetClass);
- Class javaHandlerClass = classPool.toClass(ctHandlerClass);
- Class javaFilterClass = classPool.toClass(ctFilterClass);
+ Class javaTargetClass = classPool.toClass(ctTargetClass, test.javassist.DefineClassCapability.class);
+ Class javaHandlerClass = classPool.toClass(ctHandlerClass, test.javassist.DefineClassCapability.class);
+ Class javaFilterClass = classPool.toClass(ctFilterClass, test.javassist.DefineClassCapability.class);
MethodHandler handler= (MethodHandler)javaHandlerClass.getConstructor().newInstance();
MethodFilter filter = (MethodFilter)javaFilterClass.getConstructor().newInstance();
+++ /dev/null
-package test.javassist.proxy;
-import static org.hamcrest.Matchers.arrayWithSize;
-import static org.hamcrest.Matchers.both;
-import static org.hamcrest.Matchers.endsWith;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.not;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.hamcrest.Matchers.startsWith;
-import static org.hamcrest.Matchers.stringContainsInOrder;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.security.ProtectionDomain;
-import java.util.Arrays;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import javassist.ClassPool;
-import javassist.CtClass;
-import javassist.util.proxy.DefineClassHelper;
-
-public class TestSecuredPrivileged {
-
- public TestSecuredPrivileged() {
- }
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
- /**
- * Test proves that you cannot even access members with
- * private static and final modifiers. */
- @Test
- public void testDefinedHelperPrivilegedFieldVisibility() {
- try {
- Field privi = DefineClassHelper.class.getDeclaredField("privileged");
- assertTrue(Modifier.isStatic(privi.getModifiers()));
- thrown.expectCause(instanceOf(IllegalAccessException.class));
- thrown.expectMessage(both(stringContainsInOrder(Arrays.asList("cannot access a member")))
- .and(stringContainsInOrder(Arrays.asList("with modifiers \"private static final".split("", 1)))));
-
- privi.get(null);
- } catch(Throwable t) {
- throw new RuntimeException(t);
- }
- }
- /**
- * Test proves that the default enum constant is a class and specifically
- * auto selected for Java 9. */
- @Test
- public void testDefinedHelperPrivilegedField() {
- try {
- Field privi = DefineClassHelper.class.getDeclaredField("privileged");
- assertTrue(Modifier.isStatic(privi.getModifiers()));
- Constructor<DefineClassHelper> con = DefineClassHelper.class.getDeclaredConstructor();
- con.setAccessible(true);
- DefineClassHelper inst = con.newInstance();
- assertThat(inst, instanceOf(DefineClassHelper.class));
- privi.setAccessible(true);
- Object p = privi.get(inst);
- assertThat(""+p, equalTo("JAVA_9"));
- assertThat(p.getClass().getName(), endsWith("SecuredPrivileged$1"));
- } catch(Throwable t) {
- throw new RuntimeException(t);
- }
- }
- /**
- * Test proves that caller class security is enforced and works
- * as expected. */
- @Test
- public void testDefinedHelperPrivilegedFieldMethodAccessDenied() {
- try {
- Constructor<DefineClassHelper> con = DefineClassHelper.class.getDeclaredConstructor();
- con.setAccessible(true);
- DefineClassHelper inst = con.newInstance();
- Field privi = DefineClassHelper.class.getDeclaredField("privileged");
- privi.setAccessible(true);
- Object priviInst = privi.get(inst);
- Method defineClass = priviInst.getClass().getDeclaredMethod(
- "defineClass", new Class[] {
- String.class, byte[].class, int.class, int.class,
- ClassLoader.class, ProtectionDomain.class
- });
-
- assertThat(defineClass, notNullValue());
- defineClass.setAccessible(true);
- assertThat(defineClass.getName(), equalTo("defineClass"));
- assertTrue(defineClass.canAccess(priviInst));
- ClassPool cp = ClassPool.getDefault();
- CtClass c = cp.makeClass("a.b.C");
- byte[] bc = c.toBytecode();
-
- thrown.expectCause(instanceOf(IllegalAccessError.class));
- thrown.expectMessage(equalTo("java.lang.IllegalAccessError: Access denied for caller."));
-
- @SuppressWarnings("unused")
- Object res = defineClass.invoke(priviInst, new Object[] {
- c.getName(), bc, 0, bc.length, new ClassLoader() {},
- ClassLoader.class.getProtectionDomain()
- });
- } catch(InvocationTargetException t) {
- throw new RuntimeException(t.getTargetException());
- } catch(Throwable t) { throw new RuntimeException(t); }
- }
- /**
- * Test proves that we do have 3 enum constants in the private static
- * inner class. */
- @Test
- public void testDefinedHelperEnumClass() {
- try {
- Constructor<DefineClassHelper> con = DefineClassHelper.class.getDeclaredConstructor();
- con.setAccessible(true);
- assertThat(DefineClassHelper.class.getDeclaredClasses(), arrayWithSize(1));
- Class<?> secPriv = DefineClassHelper.class.getDeclaredClasses()[0];
- assertTrue(secPriv.isEnum());
- assertThat(secPriv.getEnumConstants(), arrayWithSize(3));
- assertThat(""+secPriv.getEnumConstants()[0], equalTo("JAVA_9"));
- assertThat(""+secPriv.getEnumConstants()[1], equalTo("JAVA_7"));
- assertThat(""+secPriv.getEnumConstants()[2], equalTo("JAVA_OTHER"));
-
- } catch (Throwable t) {t.printStackTrace();}
-
- }
- /**
- * Test proves that you cannot modify private static final reference even
- * with setAccessible(true). */
- @Test
- public void testDefinedHelperCannotSetPrivileged() {
- try {
- Constructor<DefineClassHelper> con = DefineClassHelper.class.getDeclaredConstructor();
- con.setAccessible(true);
- DefineClassHelper inst = con.newInstance();
- Class<?> secPriv = DefineClassHelper.class.getDeclaredClasses()[0];
- Object J7 = secPriv.getEnumConstants()[1];
- Field privi = DefineClassHelper.class.getDeclaredField("privileged");
- privi.setAccessible(true);
- thrown.expectCause(instanceOf(IllegalAccessException.class));
- thrown.expectMessage(startsWith("java.lang.IllegalAccessException: Can not set static final"));
- privi.set(inst, J7);
-
- } catch (Throwable t) {throw new RuntimeException(t);}
-
- }
- /**
- * Test proves that you can achieve the impossible and modify private
- * static final class reference without an instance. Now we can Mock
- * test JDK 6 to 8 functionality */
- @Test
- public void testDefinedHelperSetPrivilegedToJava7() {
- try {
- Constructor<DefineClassHelper> con = DefineClassHelper.class.getDeclaredConstructor();
- con.setAccessible(true);
- DefineClassHelper inst = con.newInstance();
- Class<?> secPriv = DefineClassHelper.class.getDeclaredClasses()[0];
- Object J9 = secPriv.getEnumConstants()[0];
- Object J7 = secPriv.getEnumConstants()[1];
- Field privi = DefineClassHelper.class.getDeclaredField("privileged");
- privi.setAccessible(true);
- Object privInst = privi.get(inst);
- Field unsf = privInst.getClass().getDeclaredField("sunMiscUnsafe");
- unsf.setAccessible(true);
- Object refu = unsf.get(privInst);
- Field tuf = refu.getClass().getDeclaredField("sunMiscUnsafeTheUnsafe");
- tuf.setAccessible(true);
- Object tu = tuf.get(refu);
- Method tu_call = tu.getClass().getMethod("call", new Class<?>[] {String.class, Object[].class});
- tu_call.setAccessible(true);
- long offset = (Long) tu_call.invoke(tu, new Object[] {"staticFieldOffset", new Object[] {privi}});
- tu_call.invoke(tu, new Object[] {"putObjectVolatile", new Object[] {DefineClassHelper.class, offset, J7}});
-
- Object p = privi.get(inst);
- assertThat(""+p, equalTo("JAVA_7"));
- assertThat(p.getClass().getName(), endsWith("SecuredPrivileged$2"));
-
- tu_call.invoke(tu, new Object[] {"putObjectVolatile", new Object[] {DefineClassHelper.class, offset, J9}});
-
- } catch (Throwable t) {t.printStackTrace();}
-
- }
- /**
- * Test proves that Java 7+ MethodHandle defineClass (or DefineClassHelper.toClass)
- * works as expected. */
- @Test
- public void testDefinedHelperJava7ToClass() {
- try {
- Constructor<DefineClassHelper> con = DefineClassHelper.class.getDeclaredConstructor();
- con.setAccessible(true);
- DefineClassHelper inst = con.newInstance();
- Class<?> secPriv = DefineClassHelper.class.getDeclaredClasses()[0];
- Object J9 = secPriv.getEnumConstants()[0];
- Object J7 = secPriv.getEnumConstants()[1];
- Field privi = DefineClassHelper.class.getDeclaredField("privileged");
- privi.setAccessible(true);
- Object privInst = privi.get(inst);
- Field unsf = privInst.getClass().getDeclaredField("sunMiscUnsafe");
- unsf.setAccessible(true);
- Object refu = unsf.get(privInst);
- Field tuf = refu.getClass().getDeclaredField("sunMiscUnsafeTheUnsafe");
- tuf.setAccessible(true);
- Object tu = tuf.get(refu);
- Method tu_call = tu.getClass().getMethod("call", new Class<?>[] {String.class, Object[].class});
- tu_call.setAccessible(true);
- long offset = (Long) tu_call.invoke(tu, new Object[] {"staticFieldOffset", new Object[] {privi}});
- tu_call.invoke(tu, new Object[] {"putObjectVolatile", new Object[] {DefineClassHelper.class, offset, J7}});
-
- ClassPool cp = ClassPool.getDefault();
- CtClass c = cp.makeClass("a.b.J7");
- byte[] bc = c.toBytecode();
- Class<?> bcCls = DefineClassHelper.toClass("a.b.J7", new ClassLoader() {}, null, bc);
- assertThat(bcCls.getName(), equalTo("a.b.J7"));
- assertThat(bcCls.getDeclaredConstructor().newInstance(),
- not(equalTo(bcCls.getDeclaredConstructor().newInstance())));
-
- tu_call.invoke(tu, new Object[] {"putObjectVolatile", new Object[] {DefineClassHelper.class, offset, J9}});
-
- } catch (Throwable t) {t.printStackTrace();}
-
- }
- /**
- * Test proves that Java 6 reflection method defineClass (or DefineClassHelper.toClass)
- * works as expected. */
- @Test
- public void testDefinedHelperJavaOtherToClass() {
- try {
- Constructor<DefineClassHelper> con = DefineClassHelper.class.getDeclaredConstructor();
- con.setAccessible(true);
- DefineClassHelper inst = con.newInstance();
- Class<?> secPriv = DefineClassHelper.class.getDeclaredClasses()[0];
- Object J9 = secPriv.getEnumConstants()[0];
- Object JO = secPriv.getEnumConstants()[2];
- Field privi = DefineClassHelper.class.getDeclaredField("privileged");
- privi.setAccessible(true);
- Object privInst = privi.get(inst);
- Field unsf = privInst.getClass().getDeclaredField("sunMiscUnsafe");
- unsf.setAccessible(true);
- Object refu = unsf.get(privInst);
- Field tuf = refu.getClass().getDeclaredField("sunMiscUnsafeTheUnsafe");
- tuf.setAccessible(true);
- Object tu = tuf.get(refu);
- Method tu_call = tu.getClass().getMethod("call", new Class<?>[] {String.class, Object[].class});
- tu_call.setAccessible(true);
- long offset = (Long) tu_call.invoke(tu, new Object[] {"staticFieldOffset", new Object[] {privi}});
- tu_call.invoke(tu, new Object[] {"putObjectVolatile", new Object[] {DefineClassHelper.class, offset, JO}});
-
- ClassPool cp = ClassPool.getDefault();
- CtClass c = cp.makeClass("a.b.JO");
- byte[] bc = c.toBytecode();
- Class<?> bcCls = DefineClassHelper.toClass("a.b.JO", new ClassLoader() {}, null, bc);
- assertThat(bcCls.getName(), equalTo("a.b.JO"));
- assertThat(bcCls.getDeclaredConstructor().newInstance(),
- not(equalTo(bcCls.getDeclaredConstructor().newInstance())));
-
- tu_call.invoke(tu, new Object[] {"putObjectVolatile", new Object[] {DefineClassHelper.class, offset, J9}});
-
- } catch (Throwable t) {t.printStackTrace();}
-
- }
- /**
- * Test proves that default Java 9 defineClass (or DefineClassHelper.toClass)
- * works as expected. */
- @Test
- public void testDefinedHelperDefaultToClass() {
- try {
- ClassPool cp = ClassPool.getDefault();
- CtClass c = cp.makeClass("a.b.D");
- byte[] bc = c.toBytecode();
- Class<?> bcCls = DefineClassHelper.toClass("a.b.D", new ClassLoader() {}, null, bc);
- assertThat(bcCls.getName(), equalTo("a.b.D"));
- assertThat(bcCls.getDeclaredConstructor().newInstance(),
- not(equalTo(bcCls.getDeclaredConstructor().newInstance())));
- } catch (Throwable t) {t.printStackTrace();}
-
- }
-}
--- /dev/null
+/*
+ * This is used as a capability for running CtClass#toClass().
+ */
+package test.javassist.tools;
+
+public class DefineClassCapability {
+}
--- /dev/null
+/*
+ * This is used as a capability for running CtClass#toClass().
+ */
+package test1;
+
+public class DefineClassCapability {
+}
--- /dev/null
+/*
+ * This is used as a capability for running CtClass#toClass().
+ */
+package test2;
+
+public class DefineClassCapability {
+}
--- /dev/null
+/*
+ * This is used as a capability for running CtClass#toClass().
+ */
+package test3;
+
+public class DefineClassCapability {
+}
--- /dev/null
+/*
+ * This is used as a capability for running CtClass#toClass().
+ */
+package test4;
+
+public class DefineClassCapability {
+}
--- /dev/null
+/*
+ * This is used as a capability for running CtClass#toClass().
+ */
+package test5;
+
+public class DefineClassCapability {
+}