How do you prepend paths to a java class? - java

I'm building an older kafka (0.8.2.2) and am getting runtime errors about a missing java class:
java.lang.NoClassDefFoundError: org/apache/kafka/common/KafkaException
When I look in libs/kafka_2.10-0.8.2.2.jar, I see the existence of kafka/common/KafkaException:
$ jar tf $CLASSPATH | grep KafkaException
kafka/common/KafkaException.class
So it appears that the build (gradlew jar) constructed the class with the org/apache missing at the start of the class path. How do I fix the path?

You can't prepend paths to a Java class. The path must correspond to the package name. In your case the class kafka.common.KafkaException is found in libs/kafka_2.10-0.8.2.2.jar and org.apache.kafka.common.KafkaException is found in libs/kafka-clients-0.8.2.2.jar.
You must include libs/kafka-clients-0.8.2.2.jar in your classpath as well.

Related

What does "Exception in thread \"main\" java.lang.NoClassDefFoundError" mean when executing java .class file?

Java and Gradle beginner's question.
I made a project directory for java and gradle test:
The directory hierarchy :
HelloWorld.java:
package foo.bar;
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, world");
}
}
build.gradle:
apply plugin:'java'
Then,gradle build this project and generated what i need.
As you see above, my problem is why doesn't this execute correctly? Even through I cd to .class path.
======================================================================
While, if I remove package foo.bar; in HelloWorld.java, and repeat gradle commands and execute at he.bak directory then the error remained the same.
But when I cd to the directory where HelloWorld.java placed. everything goes OK!Why? something related with CLASSPATH environment variables or other causes?
////////////////////////////////////////////////////////////////////
UPDATE
////////////////////////////////////////////////////////////////////
Thought you guys' warm replies, I know that I should combine the CLASSPATH and the period-separated executable .class file to figure out what's going on when executing java class file.
I experiment my thought resulting in 2 point to this question:
The -cp option path parameter A/B plus the executable file c.d.e.class finally form the A/B/c.d.e.class full path where the class is actually located.
If I specify the package in source code file with package d,I must split the full path in the form of java -cp A/B/c/d e.class. split in other ways all will result in errors.
something I am not sure here is :
When I specify my package path in my source code file, It determined the only classpath when executing corresponding executable, right?
If it is the truth, How does a project with lots of package and sources files work?
What's the root principle?
When in build/classes/main try java foo.bar.HelloWorld instead of java HelloWorld
The reason you need to specify foo.bar.HelloWorld is because you specified package foo.bar;. This tells java that the class should be in foo/bar/HelloWorld and the fully qualified name for HelloWorld is foo.bar.HelloWorld. If you want to execute the class from a different working directory however, you can specify the classpath explicitly using the -cp option, e.g., java -cp c:\myproject\build\classes\main foo.bar.HelloWorld.
By the way, the classpath default is the current working directory (i.e., .) but java -cp c:\myproject\build\classes\main foo.bar.HelloWorld will NOT have the classpath set to the current working directory if it is explicitly set using the -cp option. If you want to include the current working directory but explicitly set it, or even add more directories, you can chain them using semicolons like this: java -cp .;c:\myproject\build\classes\main foo.bar.HelloWorld. So this will include both the current working directory and the directory I specified.

NoClassDefFoundError when attempting to run from command line

Apologies in advance - I know there are many, many, many very similar questions but I wanted to ask something specific to my situation.
I have a bunch of java and jar files in the same directory. I am able to compile fine and thus end up with a number of class files in the same dir. But when I go to execute the program it gives a NoClassDefFoundError saying it can't find the specified class:
C:\Users\DB\Desktop\nextreports-integration-demo\src\ro\nextreports\integration>
java -cp ".;*.jar" SimpleDemo
Exception in thread "main" java.lang.NoClassDefFoundError: SimpleDemo (wrong nam
e: ro/nextreports/integration/SimpleDemo)
I tried the same thing from a higher-level dir but it made no difference:
C:\Users\DB\Desktop\nextreports-integration-demo\src>java -cp ".\ro\nextreports\
integration\*.jar;.\ro\nextreports\integration" SimpleDemo
Exception in thread "main" java.lang.NoClassDefFoundError: SimpleDemo (wrong nam
e: ro/nextreports/integration/SimpleDemo)
The package statement in the source file is:
package ro.nextreports.integration;
I have a feeling I'm overlooking something very elementary. Thanks in advance.
Edit: Thanks very much. It works with the following:
java -cp ".\ro\nextreports\integration\nextreports-engine-6.3.jar;.\ro\nextreports\integration\commons-jexl-2.1.1.jar;.\ro\nextreports\integration\commons-logging-1.1.1.jar;.\ro\nextreports\integration\derby-10.10.1.1.jar;.\ro\nextreports\integration\itext-2.1.7.jar;.\ro\nextreports\integration\itext-rtf-2.1.7.jar;.\ro\nextreports\integration\itextpdf-5.0.6.jar;.\ro\nextreports\integration\jcalendar-1.3.2.jar;.\ro\nextreports\integration\jcommon-1.0.15.jar;.\ro\nextreports\integration\jfreechart-1.0.12.jar;.\ro\nextreports\integration\jofc2-1.0.1.jar;.\ro\nextreports\integration\mysql-connector-java-5.1.23-bin.jar;.\ro\nextreports\integration\mysql-connector-java-5.1.23-bin.jar;.\ro\nextreports\integration\poi-3.7.jar;.\ro\nextreports\integration\winstone-lite-0.9.10.jar;.\ro\nextreports\integration\xstream-1.3.1.jar;" ro.nextreports.integration.SimpleDemo
But why can I not use wildcards for the *.jar files? For instance, the following leads to a NoClassDefFoundError for a class in any jar file I don't make explicit:
java -cp ".;.\ro\nextreports\integration\*.jar" ro.nextreports.integration.
SimpleDemo
Suppose this is your directory tree:
src/
ro/
nextreports/
integration/
SimpleDemo.class
From your package declaration, your compiled class should be in the integration subdiretory. Check that there really is a SimpleDemo.class in that directory. If that is correct, its classpath includes the contents of the src directory.
That means that, if you didn't have any JAR dependencies, you could run your application from the src directory like this:
java -cp . ro.nextreports.integration.SimpleDemo
You need to use the fully qualified class name.
Since you do have jars, you have to include them in the classpath as well. Suppose you have one JAR in the directory above src, and another in the current directory, you could use:
java -cp ../one.jar;another.jar;. ro.nextreports.integration.SimpleDemo
If you run it from another directory, it will still work if you review the classpath's relative directories or use absolute directories to describe your classpath. I am not sure but usually the current directory is always included in the classpath by the java executable.

default classpath current directory anomaly

I am trying to compile and run simple Java program. This program basically prints out hello world phrase. I am not specifying -cp option and I don't have CLASSPATH environment variable. Hence the user classpath is limited only to current directory.
Now, compilation works beautifully.
rustam#rustam-laptop:~/temp/bird_test$ javac Sparrow.java
This command produces needed .class file. The weird stuff happens when I try to run .class file. The following command works good.
rustam#rustam-laptop:~/temp/bird_test$ java Sparrow
But when I try the following command
rustam#rustam-laptop:~/temp/bird_test$ java ./Sparrow
I receive the following error:
Error: Could not find or load main class ..Sparrow
WTF! i thought that symbol ./ refers to current directory.
java takes a class name as argument. It doesn't take a file path. The class name (Sparrow) is then resolved by the java class loader to a .class file based on the classpath, i.e. it looks for a Sparrow.class file in every directory and jar listed in the classpath.
Let's take an example that respects good practices, and thus doesn't use the default package:
package foo.bar;
public class Baz {
...
}
The class name of the above class is foo.bar.Baz. To execute it, you must use
java foo.bar.Baz
and java will look for a foo/bar/Baz.class in all the directories listed in the classpath. So if the classpath is set to /hello/world, it will look for the file /hello/world/foo/bar/Baz.class.

Hadoop: strange ClassNotFoundException

I am getting a classnotfound exception. The class which is claimed to be not found does not exist, but the class name is set as the path to the list of input files for my map reduce jobs.
INFO server Running: /usr/lib/hadoop/bin/hadoop --config /var/run/cloudera-scm-agent/process/155-hue/JOBSUBD/hadoop-conf jar tmp.jar /user/hduser/datasets/ /user/hduser/tmp/job_20/ mongodb://slave15/db_8.job_20
Exception in thread "main" java.lang.ClassNotFoundException: /user/hduser/datasets/
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at org.apache.hadoop.util.RunJar.main(Runjar.java:190)
As we can see, the /user/hduser/datasets/ is the path to the input files. Why am I getting this error as ClassNotFoundException? Why does it see it as a class?
I found my own error. I have a package structure. I need to specify my package information
/usr/lib/hadoop/bin/hadoop
--config /var/run/cloudera-scm-agent/process/155-hue/JOBSUBD/hadoop-conf
jar tmp.jar org.myorg.tmp /user/hduser/datasets/
/user/hduser/tmp/job_20/ mongodb://slave15/db_8.job_20
In my tool, there is no option for giving the package as argument to Java. So I need to have no packaging. But then I am having the following error since the argument before this input file path is missing.
My classes are directly in the tmp.jar in its root. I mean no org.myorg etc...
SOLUTION:
jar cmf [manifest_file] [jar_name.jar] -C [folder_of_classes] [path_for_jar_file]
it will merge the content of the manifest_file with the generated manifest file in the jar archive. Include the following line in the manifest_file
Main-Class: [Name_Of_Class]
Whether or not there's a package hierarchy (and if there isn't, you've done Something Wrong) you still need to give it the name of the class containing main.
For example, the docs have an example where the main class is org.myorg.WordCount. Even if WordCount was in the default package, it should be specified if the jar file doesn't include a main class in the manifest:
bin/hadoop jar /usr/joe/wordcount.jar WordCount /usr/joe/wordcount/input /usr/joe/wordcount/output
I'd assume you could also specify the main class in the manifest as with any jar; the class argument is shown as optional in those same docs.

Troubleshoot NoClassDefFoundError in Java

I have a Java program called Main.java, it is located in the following directory:
/home/user/program/Main.java
When I try to run Main.java from the 'program' directory, everything goes ok, I use this line:
/home/user/program$ java Main
But when I try to run Main.java from the home directory :
/home$ java /home/user/program/Main
I get :
Exception in thread "main" java.lang.NoClassDefFoundError: /home/user/program/Main
Caused by: java.lang.ClassNotFoundException: .home.user.program.Main
What is the cause of this error?
This is due to your classpath, which will default to the current directory. When you run java Main from /home/user/program it finds the class in the current directory (since the package seems to be unset, meaning it is the default). Hence, it finds the class in /home/user/program/Main.class.
Running java /home/user/program/Main from /home tries to find the class in the classpath (the current directory) which will look in /home/home/user/program expecting to find the file Main.class containing a definition of the Main class with package .home.user.program.
Extra detail: I think the java
launcher is trying to be nice by
converting /-notation for a classname
to the .-notation; and when you run
java /home/user/program/Main it is
actually running java
.home.user.program.Main for you. This
is because you shouldn't be specifying
a file, but a fully specified
classname (ie including package
specifier). And when a class has a package
java expects to find that class within a
directory structure that matches the package
name, inside a directory (or jar) in the
classpath; hence, it will try to look in
/home/home/user/program for the class file
You can fix it by specifying your classpath with -cp or -classpath:
java -cp /home/user/program Main
Because its looking for the class using the fullname you give (/home/user/program/Main). You should only look for the Main class but using the good classpath :
java Main -cp /home/user/program
Which means it'll search the Main class in the given set of paths
Your 2nd command version does not know where to find the classes.
You need to provide the so called classpath
/home$ java -cp userprogram Main
Because of what you say I conclude this:
Main is in "top" (root) package
And when you execute java you must indicate the classpath, it is, the root directory where your pakage and classes structure is located.
In your case it is the very /home/user/program. And I guess your classpath is defined as "." (the dir you are located at). When you call java from home the classpath is being taken erroneosly.
If you want to call your main using a different package declare the package at the top of the class:
package user.program;
And set the classpath to /home (or execute java from that dir).
Next call java this way:
java user.program.Main
using dots because its a full class name (indicating packages). That is translated to dirs concatenating classpath + package + class. By example:
/home
user.program -> user/program/
Main -> Main.class
Good luck!
The problem is that if you call java /home/user/program/Main the package Main is in is meant to be home.user.program, which I assume is not true for Main (I assume it's in the default package, i.e. none at all). Is there a package declaration at the top of Main?
I'd suggest to use the classpath suggestions in the other answers.
This works for me:
java -cp /home/user/program Main
just a while ago faced this kind of error of (NoClassDefFoundError). I imported some third party library in my android app using eclipse env. I got this error during a runtime - some class from this third party library couldn't be found and a result of this NoClassDefFoundError was thrown, despite the mentioned library correctly appeared in classpath, so I really didn't know what else can be done to solve this problem.
While playing with "Order and Export" tab within "Java Build Path", I put my imported third party library to the top of the list of all libraries in my project and checked its checkbox - this solved the problem
I came across this same error when trying to compile and run it. The book, "Head First Java" explains and addresses this problem appropriately. Here is a screenshot from the book for your reference.
Hope its helpful.

Categories

Resources