Java URLClassLoader does not recognize string

I have a really weird problem.

I am using URLClassLoader to dynamically import files from a directory. The code works fine if I use a literal string and works fine if I use a variable in a literal string, but that is not what I need.

package test; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; public class Test { public static void main(String[] args) { try { File subfolder = new File("C:\\temp\\"); URL classUrl = subfolder.toURI().toURL(); URL[] classUrls = { classUrl }; URLClassLoader ucl = new URLClassLoader(classUrls); for (File f : subfolder.listFiles()) { String name = f.getName() .substring(0, f.getName().lastIndexOf(".")).trim(); if (name.equals("TestClass")) System.out.println(name); try { MyInterface de = (MyInterface) Class.forName("TestClass", true, ucl) .newInstance(); de.printSomething(); } catch (ClassNotFoundException e) { } ucl.close(); } } catch (MalformedURLException e) { } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 

I need this to be possible:

 MyInterface de = (MyInterface) Class.forName(name, true, ucl).newInstance(); 

But it does not work, although "name" is a valid string and is equal to "TestClass".

EDIT: I get an error:

 java.lang.ClassNotFoundException: TestClass at java.net.URLClassLoader$1.run(Unknown Source) at java.net.URLClassLoader$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) at test.Test.main(Test.java:25) 

What's wrong?

+4
source share
4 answers

I think this is due to ucl.close () inside the for loop. I added some tests if there are directories: the next class works and initializes itself if it is declared in the root package, and if eclipse is configured to create a .class file in the bin directory,

 public class Toto { public Toto(){ // this writes "Toto" in the console if the class is well instanciated System.out.println("Toto"); } public static void main(String[] args) { try { File subfolder = new File("bin"); URL classUrl = subfolder.toURI().toURL(); URL[] classUrls = { classUrl }; URLClassLoader ucl = new URLClassLoader(classUrls); for (File f : subfolder.listFiles()) { String fileName= f.getName(); int suffix = fileName.lastIndexOf('.'); if(f.isDirectory() || suffix==-1){ continue; } String name = fileName.substring(0, suffix); try { Class.forName(name, true, ucl).newInstance(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } ucl.close(); } catch (MalformedURLException e) { } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } 
+4
source

It looks like your problem is because your class being loaded has a package. When Java loads these classes, it expects to find the directory structure associated with this package. So the following code works:

 try { File subfolder = new File("/home/glen/TestClass"); URL classUrl = subfolder.toURI().toURL(); URL[] classUrls = { classUrl }; URLClassLoader ucl = new URLClassLoader(classUrls); for (File f : subfolder.listFiles()[0].listFiles()) { System.out.println(f.getName()); String name = f.getName() .substring(0, f.getName().lastIndexOf(".")).trim();// "TestClass"; if (name.equals("TestClass")) System.out.println(name); try { MyInterface de = (MyInterface) Class.forName("test." + name, true, ucl) .newInstance(); de.printSomething(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } ucl.close(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } 

Note that I:

  • Setting the fully test.TestClass class name test.TestClass in the Class.forName method
  • Enumeration through the first subdirectory (in my case, the "test" directory) of the download folder. There is the file TestClass.class. If I try to download directly there, with or without a package name, it fails.

Essentially, URLClassLoader requires a JAR-like directory structure, such as test/TestClass.class , with a root URL that contains the directory structure.

My working theory is that you are not just changing the name variable to a string literal, as when I do this, it still works fine. Double check that you are not changing anything. In any case, I hope this points you in the right direction.

+4
source

What's wrong?

The first thing that is wrong is that it is not real code. This code catches and ignores ClassNotFoundException :

 } catch (ClassNotFoundException e) { } 

Thus, it cannot produce a displayed result.

Secondly, it is not true that when this is fixed, the code works as expected.

Unable to play.

Obviously, you did not use the code that you thought you were using. Java simply does not behave as claimed.

+3
source

Instead

 MyInterface de = (MyInterface) Class.forName(name, true, ucl).newInstance(); 

using

 MyInterface de = (MyInterface) Class.forName(name + "Class", true, ucl).newInstance(); 

works for me.

+2
source

All Articles