Link to home
Start Free TrialLog in
Avatar of Joegal
Joegal

asked on

ClassLoader problem

I have my main class and bunch of other classes (Say aClass and bClass) in a particular directory (/projects/classes/) and I use URLclassloader to load some other dynamic jar present in /usr/j2se/jre/lib/ext/ (say dynamicClass.jar). When I run my main class, its working fine till it loads the dynamic jar. Infact its even loading the dynamic jar.

The dynamic jar uses my normal classes (it has reference to aClass and bClass). The problem arises here.  I get "Exception in thread "main" java.lang.NoClassDefFoundError" . In my classpath, I have the path of my normal classes (aClass, bClass) and extensions. I dont know why the class in dynamicClass.jar file is unable to find my normal classes (aClass, bClass). They are in the classpath.


The portions of the code in the classes as described above:

Main class:

aClass whatever = new aClass();
int value = aClass.getValue();
........................................................
........................................................

String className = "dynamicClass";
Class classLoaded = Class.forName(className, true, ClassLoader.getSystemClassLoader());
 // Create an instance of the class

//WORKS FINE TILL HERE
classInstance = classLoaded.newInstance(); //FAILS (Look at dynamicClass)

dynamicClass:

aClass aObject = new aClass; //FAILS
String aThing = aClass.getThing();

My class path:

java -classpath ../classes:/usr/j2se/jre/lib/ext/dynamicClass.jar$CLASSPATH -Djava.library.path=/projects/classes/mainClass


I tried including aClass and bClass in the classpath. It wouldn't work. If I jar up the aClass and bClass and place them under extension directory (i.e. :/usr/j2se/jre/lib/ext/), it works. Thats not what I want. I do not want to deliver my normal classes to extension directory.

I read an article on Classloaders at http://www.javageeks.com/Papers/ClassForName/ClassForName.pdf

But it did not help.

Thanks in advance.

Avatar of Mick Barry
Mick Barry
Flag of Australia image

> classInstance = classLoaded.newInstance(); //FAILS (Look at dynamicClass)

what error?

Where is dynamicClass?
where are you using URLClassLoader?
Avatar of jimmack
jimmack

You shouldn't need to include the /jre/lib/ext path in your classpath.  The class loader should look in there automatically.  (No doubt objects or CEHJ will correct this if it's wrong ;-)).

Are you sure that ../classes is correct?  This implies that you're executing the java command from another directory with the same parent as "classes".

The $CLASSPATH may also be a problem.  It depends what it expands to.

Finally, I don't think you need the -D option.

This leaves us with ... er ...

java -classpath ../classes YourClass

(If the ../classes is correct).
Avatar of Joegal

ASKER

Hi,

I tried both URLClassLoader and ClassLoader. None of them makes difference. The error I encounter is "Exception in thread "main" java.lang.NoClassDefFoundError"

Let me re-phrase the problem precisely in steps:

1) I have three classes "mainClass", "aClass" and "bClass" in a directory /projects/classes

2) I have a class "dynamicClass" in extension directory /usr/j2se/jre/lib/ext/ as "dynamicClass.jar" file which uses objects "aClass" and "bClass" in its code

3) I am trying to load the "dynamicClass" using ClassLoader (or URLClassLoader) from my "mainClass"

4) My "mainClass" is able to find the dynamicClass successfully in the extension directory

5) But my "dynamicClass" is unable to find "aClass" and "bClass" (Read step 2 to understand how the dynamicClass uses "aClass" and "bClass"  -  I basically do aClass aObject = new aClass .....). I get an error "Exception in thread "main" java.lang.NoClassDefFoundError:aClass"

6) If I create 2 jars "aClass.jar" and "bClass.jar" and put them in /usr/j2se/jre/lib/ext/ directory (the same one as "dynamicClass.jar" directory), I dont see an problem.

I would like to know how I can fix the problem in step 5 without doing step 6. How do I setup the classpath so that the class found in extension directory can reference other normal classes? Do I need to use "Class.forName(className, true, ClassLoader.getSystemClassLoader());" in a different manner?

Thanks.


> The error I encounter is "Exception in thread "main" java.lang.NoClassDefFoundError"

You shouldn't get that error from newInstance, are you sure its not coming from Class.forName(). Can you post the full stack trace.

> I would like to know how I can fix the problem in step 5 without doing step 6

they need to be available to the classloader, whichever that may be. So for the system classloader to find them you'd need to add /projects/classes to the classpath.
For ULRClassLoader to find them you'd need to pass the the URL to that directory in the url list passed to its ctor.
Avatar of Joegal

ASKER

Objects,

I am sure as the code when run is able to system out "Success" but its not printing "Success2" as the code is failing in  "classInstance = classLoaded.newInstance();" in my following code.  

Regarding the classpath, I already have "/projects/classes" in my classpath (java -classpath ../classes:/usr/j2se/jre/lib/ext/dynamicClass.jar$CLASSPATH -Djava.library.path=/projects/classes/mainClass). I am running my code from /projects/bin through a run shell script (that why I have ../classes).

classLoaded = Class.forName(className, true, Thread.currentThread().getContextClassLoader());
System.out.println("Success");
//classLoaded = Class.forName(className, true, ClassLoader.getSystemClassLoader(
//));
 // Create an instance of the class
 classInstance = classLoaded.newInstance();
System.out.println("Success 2");

Let me know if you need any more details.

Thanks.
Avatar of Joegal

ASKER

Objects,

Stack trace looks like:

Exception in thread "main" java.lang.NoClassDefFoundError: xyz/om/main/uto/aClass
        at xyz.om.main.uto.dynamicClass.<init>(dynamicClass.java:54)
            at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:274)
        at java.lang.Class.newInstance0(Class.java:308)
        at java.lang.Class.newInstance(Class.java:261)
        at xyz.om.main.uto.mainClass.setClassLoader(mainClass.java:500

Thanks.
> I am sure as the code when run is able to system out "Success" but its not printing "Success2"

printing out the stack trace will verify where the exception is coming from

> ../classes:/usr/j2se/jre/lib/ext/dynamicClass.jar

using a relative entry means you have to run it from the correct directory. Using an absolute dir means you can run it from anywhere.
Its also unecessary to include jar's in the ext directory, they are automatically checked.

Are your classes in packages?

> -Djava.library.path=/projects/classes/mainClass

this aint necessary and not even sure its advisable. whats your reason for it.
> Stack trace looks like:

I see, its finding dynamicClass, but then can't find aClass.
Which does appear to be in a package, so it needs to be in a directory structure matching its package.
Which looks like it should be in:
/projects/classes/xyz/om/main/uto
Avatar of Joegal

ASKER

I have them in a package as mentioned by you. I have aClass, bClass, mainClass in the path /projects/classes/xyz/om/main/uto

I am really confused why its unable to find them.
Avatar of Joegal

ASKER

I tried manually creating a directory structure /xyz/om/main/uto under root directory and put the classes under it. It did not work then also.

I also tried creating the directory structure /xyz/om/main/uto under extensions directory and put the classes under it. It did not work.

The only time it works is when I jar the aClass and bClass and put them under extension directory (i.e. the same dir as dynamicClass.jar).


> String className = "dynamicClass";

shouldn't that be:

String className = "xyz.om.main.uto.dynamicClass";

And just to step back a little can we just use:

new dynamicClass()

and run it with:

java -classpath /projects/classes xyz.om.main.uto.mainClass
ASKER CERTIFIED SOLUTION
Avatar of Mick Barry
Mick Barry
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Joegal

ASKER

Objects,

I cannot use "new dynamicClass()" as I dont know what the class name would be in advance. Its a "dynamic" one which I have to read run time.

And regarding the String className = "xyz.om.main.uto.dynamicClass", I am using "xyz.om.main.uto.dynamicClass" only. Thats why I am able to load it. The problem I am getting is where "xyz.om.main.uto.dynamicClass" is uanble to find "xyz.om.main.uto.aClass"

Thanks.

> I cannot use "new dynamicClass()"

it was just for a test.
or try:

Class classLoaded = Class.forName(className);

what do you get when you run:

java -classpath /projects/classes xyz.om.main.uto.mainClass
Avatar of Joegal

ASKER

I still get the same error:-(
something very strange going on.

can you post the source for all files, and what directory the classes are contained in.
Avatar of Joegal

ASKER

Sorry I cannot post all files. I will try to provide more details. I appreciate your help.
Avatar of Joegal

ASKER

I decided to put all my classes in ext directory to resolve the problem as I could not find the way out. Thanks to Objects for help. Hence I would like to grant him the points.