Java classloading running extremely slow?

10,042

Solution 1

At 30 seconds, you should be able to "profile" your code and see exactly where the problem lies (in loading of the class? in creating the instance? in looking up the method? etc?)

Since it's taking 30 seconds (and not something much smaller, on the order of 10ms or so), you can just use System.out.println(new Date()); between each line of your code.

I suspect you'll find it's the loader.loadClass(String) taking so long - and I suspect that you'll find you either have a very long classpath, or a classpath that includes a network resource of some sort.

Solution 2

Check your default classpath. Maybe it refers to an unavailable network share or something like that.

Solution 3

It's possible that when you create the instance it causes many other classes to load, some of which have static initializers that do stuff that takes a long time. Put this code in a loop and see what subsequent object creations cost.

Edit: Cool, based on your profiling this sounds like you're getting close to the root cause. Another thing to consider is if you are using libraries that have big startup costs. I use iBatis to manage our interactions with Oracle, and when it first fires up it reads in a bunch of XML files and processes the query patterns in them. There's a noticable lag. It'd be interesting to hear what you find out, but you might decide the one time cost is tolerable.

Solution 4

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

ClassLoaderTest.class.getClassLoader()

, where ClassLoaderTest is the class you're running in. Or, provided if you're not running in a static context, then:

this.getClass().getClassLoader()`  

Either of these will save you instantiating a new class loader.

But I don't know if this will even help you (you have to profile), and reflection is always going to be noticeably slower. There's no getting around that. Of course, it should be used minimally in production, for this and other reasons.

EDIT: Since loadClass is taking most of the time, it could be that C:\jtest is cluttered. You can try putting Foo.class alone in a directory and using that as the URL. Of course, the reason it is faster the second time is that Foo is already loaded.

Solution 5

There's nothing wrong with your code... I was able to compile your program in less than a second. I'm running java 1.6.11 on Vista Business.

Perhaps your public string doit(string arg) method is what's taking so long. Can you try invoking it without using reflection to see if it takes a long time? Try having doit() simply return the parameter you pass in (rather than reverse the characters) to see if your reversal algorithm is what's slowing it down.

Share:
10,042
Lucky
Author by

Lucky

Updated on June 21, 2022

Comments

  • Lucky
    Lucky almost 2 years

    I'm trying to load a java .class file dynamically and call it by reflection.

    I've got a class called Foo; it has an empty constructor and has one method called doit() which takes a String argument and returns a String. Also it reverses the String.

    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 about 30 seconds to complete. I know reflection is slow, but I expect it to be 10 ms or something.

    I'm using Eclipse with JRE 1.6.0_13, and I'm running Windows Vista.

    What am I doing wrong here?

    Thanks.

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

    Edit: I've put the code in a loop; the slow function somehow gets optimized and takes 30 seconds only on the first loop.

    Edit: I've found the solution.

    Instead of:

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

    I changed it to:

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

    Now it works perfectly. I don't know why it works, but I don't see how I (and 5 other people) could have missed that. Now I feel dumb..

  • Matthew Flaschen
    Matthew Flaschen almost 15 years
    He said it took 30 seconds to complete. I assume this means to complete execution, not to compile.
  • Cuga
    Cuga almost 15 years
    It compiled and ran in less than a second. That's why I told him to try executing it with a different implementation of his doit() method.
  • Erich Kitzmueller
    Erich Kitzmueller almost 15 years
    or check the settings in Eclipse
  • Joachim Sauer
    Joachim Sauer over 14 years
    @unknown: in that case (and if you solved the problem) you should post the answer that you know is correct and accept that one.