Loading Java classes is very slow?

I am trying to load a java.class file dynamically and call it reflection.

I have a class called Foo; it has an empty constructor and has one method called doit () that takes a String argument and returns a string. It also changes the direction of the line.

Here is my code:

URL url = new URL("file://C:/jtest/"); URLClassLoader loader = new URLClassLoader(new URL[]{url}); Class<?> cl = loader.loadClass("Foo"); Constructor<?> cons = cl.getConstructor((Class[])null); Object ins = cons.newInstance(new Object[]{}); Method meth = cl.getDeclaredMethod("doit", String.class); Object ret = meth.invoke(ins, new Object[]{"!dlroW olleH"}); System.out.println((String)ret); 

As expected, this prints "Hello World!" However, it takes 30 seconds to complete. I know that reflection is slow, but I expect it to be 10 ms or something like that.

I am using Eclipse with JRE 1.6.0_13 and I am running Windows Vista.

What am I doing wrong here?

Thanks.

Edit: I have profiled the code, and all its time is used in the third line (loadClass ()). Everything else happens instantly.

Edit: I put the code in a loop; the slow function is somehow optimized and takes 30 seconds only in the first cycle.

Edit: I found a solution.

Instead:

URL url = new URL("file://C:/jtest/");

I changed it to:

URL url = new URL("file:/C:/jtest/");

Now it works great. I don’t know why this works, but I don’t understand how I (and 5 more people) could have missed it. Now I feel stupid.

+7
java performance reflection
source share
6 answers

After 30 seconds, you should be able to "profile" your code and see exactly where the problem is (when loading a class? When creating an instance? When searching for a method? Etc.?)

Since it takes 30 seconds (and not much less, of the order of 10 ms or so), you can simply use System.out.println(new Date()); between each line of your code.

I suspect you will find that loader.loadClass (String) takes so long - and I suspect that you will find that you either have a very long class path or class path that contains some kind of network resource.

+5
source share

For information: Perhaps you are a little late, but I came across the same problem and found this post.

It seems that // causes a remote search if you use the -verbose class: the class is loaded by UnknownHostException, so it must be thrown internally during class loading.

I tried the following:

URL url = new URL ("file: // localhost / C: / jtest /");

and it works (almost) as fast as your only slash solution.

+6
source share

Check your default path. Perhaps this refers to an inaccessible network share or the like.

+5
source share

Perhaps when you instantiate it it loads many other classes, some of which have static initializers that do things that take a lot of time. Put this code in a loop and see what subsequent object creation is worth.

Change Cool, based on your profiling, it sounds like you're approaching a root cause. Another thing is if you use libraries that have high startup costs. I use iBatis to manage our interactions with Oracle, and when it first starts, it reads a bunch of XML files and processes sample requests in them. There is a noticeable lag. It would be interesting to hear what you learn, but you can decide that a one-time cost is acceptable.

+3
source share

There is nothing wrong with the code ... I was able to compile your program in less than a second. I am running java 1.6.11 in Vista Business.

Perhaps your public string doit(string arg) method is what takes so long. Can you try using it without using reflection to see if it takes a long time? Try doit() simply return the parameter you are passing (instead of flipping the characters) to see if your reversal algorithm is what slows it down.

+2
source share

Is it possible for you to put Foo in CLASSPATH by default so that you can just use something like:

 ClassLoaderTest.class.getClassLoader() 

where ClassLoaderTest is the class you are working in. Or, if you are not working in a static context, then:

 this.getClass().getClassLoader()` 

Any of these will allow you to instantiate a new class loader.

But I do not know if this will help you (you need to profile), and the reflection will always be noticeably slower. There is no way. Of course, it should be used minimally in production for this and other reasons.

EDIT: Since loadClass takes up most of the time, it is possible that C: \ jtest is cluttered. You can try putting Foo.class in a directory and use this as a url. Of course, the reason is that the second time is faster than Foo is already loaded.

+2
source share

All Articles