Skip to content

Commit

Permalink
Track defined classes and add hasClass
Browse files Browse the repository at this point in the history
This helps avoid exceptions when probing for possibly-defined
invokers. Just using findResource will not pick up generated
classes, so this instead provides a hasClass that will either use
findResource or a set of all class names that have been defined at
runtime in this classloader.
  • Loading branch information
headius committed Dec 20, 2023
1 parent 13e21f6 commit 793a9a5
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -635,9 +635,8 @@ private static void loadReceiver(String typePath, JavaMethodDescriptor desc, Ski
private Class tryClass(String name, String path, Class targetClass, Class expectedSuperclass) {
final Class c;
try {
URL resource = classLoader.findResource(path + ".class");
if (resource == null) {
if (DEBUG) LOG.debug("could not find class file for " + name);
if (!classLoader.hasClass(name)) {
if (DEBUG) System.err.println("could not find class file for " + name);
seenUndefinedClasses = true;
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,16 @@
import java.net.URL;
import java.net.URLClassLoader;
import java.security.ProtectionDomain;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;

public class ClassDefiningJRubyClassLoader extends URLClassLoader implements ClassDefiningClassLoader {

public final static ProtectionDomain DEFAULT_DOMAIN;

private final Set<String> definedClasses = new ConcurrentSkipListSet<>();

static {
ProtectionDomain defaultDomain = null;
try {
Expand All @@ -50,10 +55,24 @@ public ClassDefiningJRubyClassLoader(ClassLoader parent) {
}

public Class<?> defineClass(String name, byte[] bytes) {
return super.defineClass(name, bytes, 0, bytes.length, DEFAULT_DOMAIN);
Class<?> aClass = super.defineClass(name, bytes, 0, bytes.length, DEFAULT_DOMAIN);
definedClasses.add(name);
return aClass;
}

public Class<?> defineClass(String name, byte[] bytes, ProtectionDomain domain) {
return super.defineClass(name, bytes, 0, bytes.length, domain);
Class<?> aClass = super.defineClass(name, bytes, 0, bytes.length, domain);
definedClasses.add(name);
return aClass;
}

/**
* Return true if the class is loadable in this classloader, false otherwise.
*
* @param name the class name
* @return whether it's loadable
*/
public boolean hasClass(String name) {
return definedClasses.contains(name) || super.findResource(name.replace('.', '/') + ".class") != null;
}
}

0 comments on commit 793a9a5

Please sign in to comment.