2

I want to load specific jars in ScriptEngineManager using specific ClassLoader

This constructor loads the implementations of ScriptEngineFactory visible to the given ClassLoader using the service provider mechanism.

The problem when I tried to create Classloader

File file = new File("c:\\myclasses\\");

try {
// Convert File to a URL
URL url = file.toURI().toURL();          // file:/c:/myclasses/
URL[] urls = new URL[]{url};

// Create a new class loader with the directory
ClassLoader cl = new URLClassLoader(urls)

And I'm getting also class that weren't in class for example Spring

 Class cls1 = cl.loadClass("org.springframework.http.HttpStatus");

How can I create a clean classloader with only specific folder's classes?

EDIT

If it's not possible, can I use in groovy script something equivalent to Rhino's ClassShutter

private static void setJavaClassesVisibleInvisibleSandbox(Context cx)
 {
  cx.setClassShutter(new ClassShutter()
   {
      public boolean visibleToScripts(String className)
      {
          // No Java classes allowed inside scripts

EDIT

When tried @Vinz243 CustomClassLoader solution failed to load classes for classes files or jar files from specific folder, even tried rt.jar

java.lang.SecurityException: Prohibited package name: java.lang
    at java.lang.ClassLoader.preDefineClass(ClassLoader.java:662)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:761)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
    at com.CustomClassLoader.loadClass(CustomClassLoader.java:15)
Ori Marko
  • 56,308
  • 23
  • 131
  • 233

1 Answers1

3

As specified in the javadoc :

public URLClassLoader(URL[] urls)

Constructs a new URLClassLoader for the specified URLs using the default delegation parent ClassLoader. The URLs will be searched in the order specified for classes and resources after first searching in the parent class loader. Any URL that ends with a '/' is assumed to refer to a directory. Otherwise, the URL is assumed to refer to a JAR file which will be downloaded and opened as needed.

So you can try to extend ClassLoader since the mechanism responsible for loading the parent class is inside java.lang.ClassLoader#loadClass(java.lang.String, boolean)

    try {
        if (parent != null) {
            c = parent.loadClass(name, false);
        } else {
            c = findBootstrapClassOrNull(name);
        }
    } catch (ClassNotFoundException e) {
        // ClassNotFoundException thrown if class not found
        // from the non-null parent class loader
    }

EDIT

Not tested, but something like that should do the job:

class CustomClassLoader extends URLClassLoader {

    public CustomClassLoader (URL[] urls) throws NoSuchMethodException {
        super(urls);
    }

    @Override
    protected Class<?> loadClass (String name, boolean resolve) throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            Class<?> aClass = findClass(name);
            if (resolve) {
                resolveClass(aClass);
            }
            return aClass;
        }
    }
}
Community
  • 1
  • 1
Vinz243
  • 9,654
  • 10
  • 42
  • 86
  • ClassLoader can't be accessed `private final ClassLoader parent` – Ori Marko Jul 03 '19 at 07:31
  • I mean extend the ClassLoader/URLClassLoader rather modifying the `URLClassLoader` class – Vinz243 Jul 03 '19 at 07:32
  • I tried to extend and `parent` can't be used *The field ClassLoader.parent is not visible* – Ori Marko Jul 03 '19 at 07:32
  • Why do you need to access parent? Your implementation shouldn't be using it – Vinz243 Jul 03 '19 at 07:51
  • I tried your suggestion to *extend `ClassLoader`* and using `if (parent != null) {`, can you explain your answer? – Ori Marko Jul 03 '19 at 07:56
  • I would rather extends URLClassloader, see post edit – Vinz243 Jul 03 '19 at 08:52
  • I tried your solution, but now it doesn't recognize classes inside the specific folder or classes inside jars. excpetion: `java.lang.ClassNotFoundException: net.minidev.asm.FieldFilter at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at com.CustomClassLoader.loadClass(CustomClassLoader.java:15) at java.lang.ClassLoader.loadClass(ClassLoader.java:357)` – Ori Marko Jul 03 '19 at 09:00
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/195915/discussion-between-vinz243-and-user7294900). – Vinz243 Jul 03 '19 at 09:13