Skip to content

Commit

Permalink
changes CtClass#toClass() and ClassPool#toClass() etc. to support Jav…
Browse files Browse the repository at this point in the history
…a 11,

in other words, java.lang.invoke.MethodHandles.Lookup.
  • Loading branch information
chibash committed Sep 8, 2018
1 parent 0958148 commit 6320bc4
Show file tree
Hide file tree
Showing 27 changed files with 532 additions and 451 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Expand Up @@ -12,4 +12,4 @@ tmp/
.project
.settings
TestLog.xml

*~
1 change: 1 addition & 0 deletions Readme.html
Expand Up @@ -283,6 +283,7 @@ <h2>Changes</h2>

<p>-version 3.24
<ul>
<li>Java 11 supports.</li>
<li>JIRA JASSIST-267.</li>
<li>Github PR #218.</li>
</ul>
Expand Down
134 changes: 123 additions & 11 deletions src/main/javassist/ClassPool.java
Expand Up @@ -1023,16 +1023,23 @@ public void appendPathList(String pathlist) throws NotFoundException {
* 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 {
Expand Down Expand Up @@ -1066,21 +1073,21 @@ static ClassLoader getContextClassLoader() {
/**
* 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);
}

/**
Expand All @@ -1092,16 +1099,17 @@ public Class toClass(CtClass ct, ClassLoader loader)
* 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>
* in <code>java.lang.Class</code>. It returns the domain that the
* 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
Expand All @@ -1112,13 +1120,117 @@ public Class toClass(CtClass ct, ClassLoader loader)
*
* @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);
Expand Down
60 changes: 56 additions & 4 deletions src/main/javassist/CtClass.java
Expand Up @@ -1271,13 +1271,65 @@ public void instrument(ExprEditor editor)
* 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
Expand Down Expand Up @@ -1316,7 +1368,7 @@ public Class<?> toClass(ClassLoader loader, ProtectionDomain domain)
if (loader == null)
loader = cp.getClassLoader();

return cp.toClass(this, loader, domain);
return cp.toClass(this, null, loader, domain);
}

/**
Expand All @@ -1332,7 +1384,7 @@ public Class<?> toClass(ClassLoader loader, ProtectionDomain domain)
public final Class<?> toClass(ClassLoader loader)
throws CannotCompileException
{
return getClassPool().toClass(this, loader);
return getClassPool().toClass(this, null, loader, null);
}

/**
Expand Down Expand Up @@ -1405,7 +1457,7 @@ public void detach() {
* @see ClassPool#doPruning
*
* @see #toBytecode()
* @see #toClass()
* @see #toClass(Class)
* @see #writeFile()
* @see #instrument(CodeConverter)
* @see #instrument(ExprEditor)
Expand Down
48 changes: 45 additions & 3 deletions src/main/javassist/Loader.java
Expand Up @@ -16,11 +16,12 @@

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;
Expand Down Expand Up @@ -138,7 +139,48 @@
* @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;
Expand Down Expand Up @@ -186,7 +228,7 @@ public Loader(ClassLoader parent, ClassPool cp) {
}

private void init(ClassPool cp) {
notDefinedHere = new Hashtable<String,ClassLoader>();
notDefinedHere = new HashMap<String,ClassLoader>();
notDefinedPackages = new Vector<String>();
source = cp;
translator = null;
Expand Down

0 comments on commit 6320bc4

Please sign in to comment.