How to run a jar file in hadoop? - java

I have created a jar file using the java file from this blog using following statements
javac -classpath /usr/local/hadoop/hadoop-core-1.0.3.jar -d /home/hduser/dir Dictionary.java
/usr/lib/jvm/jdk1.7.0_07/bin/jar cf Dictionary.jar /home/hduser/dir
Now i have tried running this jar in hadoop by hit and trial of various commands
1hduser#ubuntu:~$ /usr/local/hadoop/bin/hadoop jar Dictionary.jar
Output:
Warning: $HADOOP_HOME is deprecated.
RunJar jarFile [mainClass] args...
2.hduser#ubuntu:~$ /usr/local/hadoop/bin/hadoop jar Dictionary.jar Dictionary
Output:
Warning: $HADOOP_HOME is deprecated.
Exception in thread "main" java.lang.ClassNotFoundException: Dictionary
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at org.apache.hadoop.util.RunJar.main(RunJar.java:149)
How can i run the jar in hadoop? I have the right DFS Locations as per needed by my program.

I was able to reproduce your problem. The problem is where you are creating the jar.
Basically, the directory that you are packaging into the jar is confusing the jar file in locating the main class file. Instead if you try doing :
/usr/lib/jvm/jdk1.7.0_07/bin/jar cf Dictionary.jar /home/hduser/dir/Dictionary.class
i.e. package the class file specifically into the jar and then run:
/usr/local/hadoop/bin/hadoop jar Dictionary.jar Dictionary
It just works fine provided that you have a main function in your class called Dictionary.
The problem is when you package a full directory inside a jar then the jar also needs to be aware of the directory structure to locate the class file. For this, we need to have a well defined package hierarchy to define the class location. So, when you are packaging /home/hduser/dir/ into the jar, the jar is not aware of the location of the class file which is located deep inside this directory structure. For this you need to add a package name to your .java file according to the directory structure , for example home.hduser.dir and while running the hadoop jar command specify the class name with the package structure, for example home.hduser.dir.Dictionary.

Use the below command to run the hadoop jar file from the CLI.
hadoop jar <jarFileName> <mainClassname> <AnyCommandLineArguements>

I also ran into the same problem and the console does not show much information but just
RunJar jarFile [mainClass] args...
Please check the jar for the package folders location, as a straightforward approach please try is the package starts with com.company...
The "com" folder should be the first level folder when the jar is unpacked

Related

Wrong classpath declaration gets a java.lang.NoClassDefFoundError

I have a small project which in my local IDE is running just fine, a screenshot will show the project structure:
I have highlighted the jewelcli jar because on that class i get the exception mentioned in the header.
While running locally all goes fine, on a testing ubuntu server i get:
java -verbose -classpath "/correct/path/jarName.jar:lib/jars/*" correct.package.and.main.Class
***all bootstrapping class from RT.JAR***
java.lang.NoClassDefFoundError: uk/co/flamingpenguin/jewel/cli/ArgumentValidationException
at correct.package.and.main.Class.main(Class.java:31)
Caused by: java.lang.ClassNotFoundException: uk.co.flamingpenguin.jewel.cli.ArgumentValidationException
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
... 1 more
I dont think this is actually related at all to that jewelcli jar in particular, because i double checked and its there:
unzip -l jarname.jar | grep jewelcli
435937 11-20-11 01:22 lib/jars/jewelcli-0.7.6.jar
But it happens for that Jar because it is the very first jar that the program needs (after all the bootstrapping classes in rt.jar).
This is where i am basing my command line from
But i also see:
Subdirectories are not searched recursively. For example, foo/* looks for JAR files only in foo, not in foo/bar, foo/baz, etc.
I thought that by specifying in the command line the jar file containing all the libraries, java would automaticaly, and recursively, scan all subdirectories, but it does not work:
java -verbose -classpath "/correct/path/jarName" correct.package.and.main.Class
Any tip on how can i get java to scan the whole jar i specify in the -classpath option?
I thought that by specifying in the command line the jar file containing all the libraries, java would automaticaly, and recursively, scan all subdirectories
It depends. The standard Java classloaders do not know how to load classes from JARs that embedded inside other JARs.
And that's what you appear to have done ... if I am reading your question correctly.
There are a few ways to address this:
Copy all of the dependent JARs to the server, put them into a directory, and add the directory to the classpath; e.g.
java -classpath "/correct/path/jarName.jar:/correct/path/lib/*" \
correct.package.and.main.Class
Build an UberJAR or shaded JAR by unpacking the dependent JARs into a directory, adding your classes and producing a JAR from the tree. There are maven plugins for building such JAR files.
Use something like Spring Boot which uses a classloader that understands how to deal with JARs withing JARs.

Error while running jar file on system

I am having a java file like the following:
import org.xBaseJ.DBF;
import org.xBaseJ.fields.CharField;
import org.xBaseJ.fields.NumField;
import org.apache.log4j.*;
public class Example2 {
public static void main(String args[]){
..........
}
}
I have created the this to 'Example2.jar' file to run by following the steps below:
1) javac Example2.java
2) java Example2
3) This will produce a .class file needed for the JAR file.
4) Next create a manifest file (saved using the extension .txt) using the text editor and input the following
Main-Class: Example2
or whatever your file's name is.
5) Next create the JAR file using this code:
jar cfe Example2.jar Example2 Example2.class
After step 5, I got a jar file named 'Example2.jar' . I tried to run the jar file using the following command:
java -jar HelloWorld.jar
But I am getting the following Errors:
Exception in thread "main" java.lang.NoClassDefFoundError: org/xBaseJ/DBF at Example2.main(Example2.java:14) Caused by: java.lang.ClassNotFoundException: org.xBaseJ.DBF at java.net.URLClassLoader$1.run(URLClassLoader.java:372) at java.net.URLClassLoader$1.run(URLClassLoader.java:361) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:360) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 1 more
I did not understand, what is the reason? Please guide me?
Well one thing is that when u are creating Jar just look this menifest first that is what can help for the including the External Libraries.
http://docs.oracle.com/javase/tutorial/deployment/jar/appman.html
While creating and giving chages to the menifest just have to run that class with the configuration
http://docs.oracle.com/javase/tutorial/deployment/jar/modman.html
so seeing both of that link.
just look this Example.
run your java and get class file
javac Test.java
and if u having some other external libraries working then do like this.
javac -classpath xxx.jar Test.java
and see the menifest configuration and make that file with external changes like this.
menifest.txt
Main-Class: Test
Class-Path: xxx.jar xxxx.jar
then u need to make jar file like this.
run this command
jar cfm jarName.jar manifest.txt Test.class
and hence we done u can have jarfile in that same path.
The error you're seeing is caused by having an incorrect classpath. I'm assuming that when you compiled the class, you somehow provided a classpath (either by passing the '-classpath' arg or by setting the 'CLASSPATH' environment variable). The problem is that the compilation classpath is separate from the runtime classpath. So, you just need to ensure that all of the dependencies (other jar files, most likely) that were on the classpath when you compiled the class are also added to the classpath when running the jar. For a jar file, this is typically done by adding a 'Class-Path'header to the manifest.
An alternative method would be to specify the classpath using either the command line arg or the environment variable and include your Example2.jar file in that classpath, and run java Example2 (without the '-jar').

Run jar file with out specify supporting jar file

I create a new jar file. when i run the jar using
java -jar UpdateAvailable.jar com.dao.mysql.UpdateAvailable
I got the following exception.
Exception in thread "main" java.lang.NoClassDefFoundError: org/codehaus/jettison/json/JSONException
Caused by: java.lang.ClassNotFoundException: org.codehaus.jettison.json.JSONException
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
But I copied all the supporting jars inside the UpdateAvailable.jar. Now what my requirement is run the jar file with out specifying supporting jars, like
java -jar UpdateAvailable.jar com.dao.mysql.UpdateAvailable
Here are some points to remember while you are working with JAR files and ClassPath: -
For making your JVM find class, your classpath should be set till the directory containing the class. In this case you have JAR.
So, you need to give the path till your Jar File Name
Now, since you have your Jar files inside your currently running Jar file, you can't set your classpath till the folder inside a Jar, so basically you won't be able to set classpath for inner Jar Files..
So, clearly JVM won't be able to see classes inside your inner Jar..
So, make sure that your required JAR files are outside of all the JAR files (I mean to say - avoid Nested JAR Files)..
I'm not sure how you are packaging your jar file, but it would sound like you need something like One-Jar to help you package your file and all your supporting libraries into a single jar. One-Jar comes with it's own classloader that allows it to load all the included jars in your executable jar file.
Configuration is fairly straight forward and easy to use. If you are using Maven, you can use the one-jar maven plugin to help you configure which libs you want included.
There are also other similar packages you can use instead of One-Jar, such as JarJar and ProGuard. Also take a quick look at this SO question.
In executable jar couldn't reads any supporting jar files inside a jar. So keep all supporting jars in a folder and place the executable jar in the same directory. And add "Class-Path" as "Supporting jar files separate with space" in "MANIFEST.MF" File. Now run the jar as
java -jar UpdateAvailable.jar com.dao.mysql.UpdateAvailable

After extracting files from a jar, how to recombine them into a valid jar again?

I extracted the files from a dacapo benchmark jar.
jar -xf dacapo-2006-10-MR2.jar
Then, I got this folder
dacapo-2006-10-MR2
I tried to recombine them together in this way:
jar cmf dacapo-2006-10-MR2/META-INF/MANIFEST.MF my-dacapo.jar dacapo-2006-10-MR2
But I got an error when I tried to use the new jar:
java -jar my-dacapo.jar -s small antlr
Exception in thread "main" java.lang.NoClassDefFoundError: Harness
Caused by: java.lang.ClassNotFoundException: Harness
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:321)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
Could not find the main class: Harness. Program will exit.
I am not familiar with the jar files. Could anyone do me a favor? Thanks!
#Bohemian It seems your solution doesn't work here, see below
> zip -r my-dacapo dacapo-2006-10-MR2
> mv my-dacapo.zip my-dacapo.jar
> java -jar my-dacapo.jar -s small antlr
Invalid or corrupt jarfile my-dacapo.jar
Thanks anyway.
A jar is just a zipped file with an extension of ".jar"
Zip up your files and rename the .zip to .jar
The Jar tool provides a u option which you can use to update the contents of an existing JAR file by modifying its manifest or by adding files.
The basic command for adding files has this format:
jar uf jar-file input-file(s)
In this command:
The u option indicates that you want to update an existing JAR
file.
The f option indicates that the JAR file to update is specified
on the command line.
jar-file is the existing JAR file that is to be updated.
input-file(s) is a space-delimited list of one or more files that you want to add to the JAR file.
Any files already in the archive having the same pathname as a file being added will be overwritten.
More detail: https://docs.oracle.com/javase/tutorial/deployment/jar/update.html
first of all go to the directory where that file are unzipped .then write command.
jar cvf (class which u want to insert).class (or folder which u want to insert)
it will generate executable jar file
If you use eclipse, there you can get your jar by follow these steps and create manifest
Also you might need to read this(you might have not define your main class in manifest file)

Why edit to Manifest file provides solution that CLASSPATH does not

I'm writing a short utility that performs a short task on a remote Oracle instance. The utility uses the Oracle jdbc driver found in ojdbc6.jar.
The Oracle jar is properly included in my classpath. When I export my project to a jar and run the jar on the command line using "java -jar ", I get:
Exception in thread "main" java.lang.ClassNotFoundException: oracle.jdbc.OracleDriver
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at java.lang.Class.forName0(Native Method)
After moving the Oracle jar into the same directory as my runnable jar file, I changed my Manifest file to include the the Oracle jar in the classpath. This fixed the problem, and my jar ran fine.
Can anyone explain why including the Oracle jar in my classpath didn't solve the problem, and why editing the Manifest file did?
Thanks!
From Sun (Oracle) documentation for the java -jar command:
Execute a program encapsulated in a JAR file. The first argument is
the name of a JAR file instead of a startup class name. In order for
this option to work, the manifest of the JAR file must contain a line
of the form Main-Class: classname. Here, classname identifies the
class having the public static void main(String[] args) method that
serves as your application's starting point. See the Jar tool
reference page and the Jar trail of the Java Tutorial for information
about working with Jar files and Jar-file manifests. When you use this
option, the JAR file is the source of all user classes, and other user
class path settings are ignored.

Categories