ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I'm trying to compile & run some simple java code ("BufferTest.java") that imports classes from apache.commons.collections (from libcommons-collections3-java package). These classes are in /usr/share/java/commons-collections3.jar.
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/collections/buffer/PriorityBuffer
at BufferTest.main(BufferTest.java:10)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.collections.buffer.PriorityBuffer
at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
at java.lang.ClassLoader.loadClass(ClassLoader.java:323)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
at java.lang.ClassLoader.loadClass(ClassLoader.java:268)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:336)
... 1 more
So, obviously I need more than just "java BufferTest".
What's the correct command to run it?
Thanks.
PS: there's not much to the code. It starts with:
Code:
import java.util.*;
import org.apache.commons.collections.buffer.PriorityBuffer;
public class IterTest {
public static void main( String[] args ) {
ArrayList<String> list = new ArrayList<String>();
PriorityBuffer buff = new PriorityBuffer();
...
Last edited by r.stiltskin; 05-17-2009 at 07:52 PM.
1. I assume (hope) you're using the Sun JDK (and not Gnu Java).
"javac -version" will tell you.
2. More important, if you're "main" is in public class "IterTest"
... then it should be in a source named "IterTest" (otherwise, it should fail with a compile error)
... and your "run" command should be something like:
And FYI, The classpath can have multiple items made up of directory paths that contain compiled classes and/or the pathnames of jar files. Individual entries must be separated by colons.
For the record, I accidentally posted the wrong code snippet earlier. The filename is BufferTest.java and the classname is BufferTest. And yes, I am using Sun JDK 6 (although I also tried open-jdk with the same lack of success).
No confusion this time; it can't get any simpler than this:
Code:
import org.apache.commons.collections.buffer.PriorityBuffer;
public class BufferTest {
public static void main( String[] args ) {
PriorityBuffer ascendingBuff = new PriorityBuffer(true);
// PriorityBuffer descendingBuff = new PriorityBuffer(false);
System.out.println("Hello");
}
}
Exception in thread "main" java.lang.NoClassDefFoundError: BufferTest
Caused by: java.lang.ClassNotFoundException: BufferTest
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
Oh, and I can run it in Eclipse by configuring Project/Properties/Java Build Path/Libraries/Add External JARs/ pointing to the exact directory that I used as the classpath on the command line.
The compiler has the concept of a "source path" in which it looks for the files you specify for compilation. It defaults to the current directory unless you override it using -sourcepath.
Maybe you misunderstood me. The compiler doesn't need the ".:"
It finds the source files in the current directory even if only the external JARs are mentioned in the command line classpath argument.
It's apparently only the JRE that needs the ".:" to find the local class files when a classpath is supplied on the command line. I was wondering why there is that inconsistency between the compiler and the runtime engine.
I understood you. My response was an attempt to answer your question "Why is it required for running & not for compiling?".
In my mind there isn't an inconsistency. The compiler needs to know how to find the sources and pre-compiled classes that the sources depend on. In your example, there are three logical path locations being used at various times. 1) the path to your source code, 2) the path to the classes generated by compiling your code, and 3) the path to commons-collections.jar. The compiler needs 1 and 3 specified as sourcepath and classpath respectively, because the source depends on commons-collections and nothing else. The JRE needs 2 and 3 because it only uses compiled code. Now here's the explanation of why you don't want all three working during compilation...
Its a bad idea to also put #2 in the classpath during compilation because by doing so you are telling the compiler that your source code is dependent on the class files generated during compilation. You might think this will never happen, but consider the following situation... a source directory with two files A.java and B.java. In the first version of this project A depends on B, so we have.
A.java
A.class
B.java
B.class
But then the developer decides to refactor the code so that B.java is no longer necessary and deletes B.java in preparation for that change.
Code:
rm B.java
But before chaning the code in A.java, the developer is distracted (by a mild earthquake for example, like there was in Los Angeles last night). When returning to the project, the code is compiled with the '.' in the classpath like so:
But the compile succeeds even thought it should fail due to the missing dependency (B.java no longer exists, but A.java was never changed). The compile succeeds here because of the '.' in the classpath and because the developer forgot to delete B.class. The remaining dependency in A.java on B.java is satisfied because B.class is found by the compiler as a result of the '.' in the classpath.
On the other hand, if the '.' was not used during compilation, the compile will fail even though B.class still remains.
Last edited by kellinwood; 05-18-2009 at 09:20 AM.
Sorry if I'm being dense, and if I didn't explain myself clearly, but despite your very detailed explanation you seem to be missing my point. Let me try to explain myself in your terms.
It appears to me that the compiler doesn't need #1 and #3 specified, but only #3. Apparently the compiler searches the current directory when no classpath is specified, AND it searches the current directory when a classpath is specified, even though the classpath list does NOT include the current directory. Thus if my code is entirely self-contained within the current directory I can compile it with the command
Code:
javac MyClass.java
and if my code depends on /usr/share/java/some-library.jar I can compile it with the command
What seems inconsistent to me is the behavior of the JRE. When no classpath is explicitly provided, the JRE by default looks in the current directory, but if ANY classpath is supplied to the JRE, ALL classpaths must be supplied explicitly, including the current directory. Thus, as you have stated, in order to RUN the program the command-line command is
> It appears to me that the compiler doesn't need #1 and #3 specified, but only #3.
I know its confusing and it may seem like splitting hairs, but #1 is the path to the *source code*, e.g. the 'source path', which is different than the classpath and defaults to the current directory if not specified. #2 is the path to the compiled classes from #1, which are the same directory in our simple examples. In larger projects or as soon as you switch to an IDE, they will be different directories (i.e., the code will be in a 'src' directory, and the classes written to a 'classes' directory). The compiler does need #1 as the source path (but it gets one, even if via a default value). My detailed explanation was meant to show why you don't want to have the path to *your* generated class files in the classpath during compilation.
But I now awaken to my own 'denseness' with your point about the classpath for the JRE. I was not aware that if you don't explicitly specify a classpath that it defaults to using the current directory. I don't have an explanation other than it seems like reasonable behaviour. But this is the viewpoint of someone who long ago gave up compiling on the command line for an IDE, so I can see how it might seem confusing to someone else.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.