Hi,

this is a very strange problem for me. I'm writing an app that uses the BouncyCastle API. I downloaded the jar file from their website and I put it in my project build path so as to use it, and it works.

However, when I try to run the app from my command line I get an error: java.lang.NoClassDefFoundError: org/bouncycastle/crypto/Digest

But when I run the same app from my eclipse IDE I get no such error. Has anyone experienced anyone like this? I mean, the class in the error is there in my buildpath, or eclipse wouldn't let me run the app. But it doesn't get picked up when I run my app from my command line.

Why?

Recommended Answers

All 20 Replies

Make sure you have the required libraries on your runtime classpath. Are you packaging your app as a JAR file or as class files? If you are running your app as a packaged JAR file make sure you have all the required dependencies present in the JAR file. If you are running a class file make sure you specify the -cp or -classpath argument to the Java process.

Edit: I just noticed you have created a lot of posts over the past few days but not marked them as solved. If your problem has been solved, please mark your posts as solved so that it might be easier for someone with the same query to find a solution.

Sorry about that sos, i'll get to marking them now.

As for my latest problem, no i havent packaged my app as a jar. I'm still in the testing phase so i still do a lot of code modifying.

How do I specify the classpath? Do you mean typing this in the command line: "java -cp . [class]"? I did that and I still get the same error

java -cp .;your/jar/one.jar;your/jar/two.jar pkg.MainClass

Run this from the directory where you have all your compiled classes. For e.g. if your class package is "test.pkg", then run it from the folder which is the parent folder of the "test" folder which in turn in the parent folder of the "pkg" folder which contains your main class.

Lol sorry, I'm a little confused. What's "you/jar/one.jar" or is that just a code? Is that the libray, in my case, bouncycastle (the library is a jar file)? And if so, does that mean I have to put the bouncy castle in the parent folder of "test" and "pkg"?

The -cp option should have the path to all the classes that the JVM needs to execute your code. If some of them are in jar files, the path to the jar file should be in the -cp option. Also a reference to the start of the package path for the class needs to be there. Depending on where the current directory is when you issue the java command, you need to set the classpath to where the package path starts. If there is no package and you are in the same directory as the .class files, use the .(dot) in the -cp to point to the current directory.
If the class is in a package, then you must point the classpath to where the package path begins.

Lol sorry, I'm a little confused. What's "you/jar/one.jar" or is that just a code? Is that the libray, in my case, bouncycastle (the library is a jar file)? And if so, does that mean I have to put the bouncy castle in the parent folder of "test" and "pkg"?

That was just a sample I posted. You can specify any number of JAR's in a similar fashion. Also, you don't need to move around your JAR's; just put the path where your Bouncy castle JAR lies and you should be good to go.

java -cp .;c:/jars/bouncy.jar;c:/jumping/jack.jar pkg.Main

Thanks. It works now! :D

So, just to be clear, when Im done and I want to create a JAR file of my app, which I would like to run the app when I double click, is it okay that I already have the bouncy castle in my buildpath before creating my app.jar? Or do I have to put the bouncy castle some place else too?

So, just to be sure, if I'm creating a jar file for my app that will work as an executable, it's okay that I have the bouncy castle in the buildpath when creating the app.jar? Or do I have to add the jar some place else to ensure that when users open the app they won't get this error.

The logical thing to do here is to package all the runtime dependencies with your application JAR i.e. have the Bouncy jar present in the application jar file you create. If you are using eclipse, it's pretty easy.

1) Right Click Project -> Export -> Java -> Runnable JAR
2) In Launch Configuration select the name of your main class
3) In export destination select the path and name for your application JAR
4) In Library handling select the second option (package required libraries...)
5) Open the newly created JAR with any unzip utility and verify whether you have a Bouncy jar placed inside the newly created JAR. If it isn't go to step 6 else step 7
6) Right Click on project -> Java build path -> Order and Export tab; ensure that the Bouncy jar is checked.
7) Fin

You are now done. Just run the generated JAR using the command:

java -jar YourAppJar.jar

and it should work without any hassles.

aww sweet. Cheers, mate

~s.o.s~

Open the newly created JAR with any unzip utility and verify whether you have a Bouncy jar placed inside the newly created JAR

Why do you want one jar file inside of another jar file?
What programs are able to access the contents of the internal jar file?

Why do you want one jar file inside of another jar file?

This is so that the JAR can be self-sufficient in executing your packaged application without relying on the user to place the JAR dependencies at pre-determined locations.

What programs are able to access the contents of the internal jar file?

AFAIK, there is no "standard" way of referring to a JAR file which is packaged within a given JAR file. Currently there are two approaches that are followed by packaging tools:

  • Approach 1: Create a custom classloader which will be the main class for our JAR and which is responsible for loading the contents of the JAR file packaged in the JAR. Here the manifest file is the one which is responsible for all the magic. In this case, we use the utility class offered by Eclipse for doing the same. Take a look at the contents of the "org" package in the attached "first-external.zip" file.
  • Approach 2: Uncompress all the dependent JAR files (e.g. log4j) and place the entire package hierarchy in the newly created JAR

Eclipse supports both the behaviors (enabled by selecting option 1 or option 2 in the "Library Handling" part which I mentioned in my previous post). I'm currently attaching the two JARs (zips, doesn't really matter) created using both the approaches in case you are interested. It's a throwaway Postfix calculator which uses log4j instead of sysouts. For executing:

java -jar first-external.zip "12 3 /"
java -jar second-external.zip "12 3 /"

Thanks. I was wondering if there was a classloader that could read the contents of an internal jar file to load classes etc

Here's what I get in the console when I run the zip files. What is the first one supposed to do? Why is it trying to get permissions?

Also the posted notes on executing the programs has a different name than the zip file:
second-external.zip vs second-internal.zip

D:\JavaDevelopment\Testing\ForumQuestions3\Security>java -Djava.security.manager -Djava.security.policy=mypolicy.policy -jar first-external.zip "12 3 /"
Exception in thread "main" java.security.AccessControlException: access denied (java.security.AllPermission <all permissions> <all actions>)
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPermission(Unknown Source)
at java.net.URLClassLoader$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.getPermissions(Unknown Source)
at java.security.SecureClassLoader.getProtectionDomain(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:54)

D:\JavaDevelopment\Testing\ForumQuestions3\Security>MORE


D:\JavaDevelopment\Testing\ForumQuestions3\Security>java -Djava.security.manager -Djava.security.policy=mypolicy.policy -jar second-internal.zip "12 3 /"
[2010-08-29 14:18:31,156] INFO 0[main] - home.projects.misc.PostfixCalculator.evaulate(LauncherTest.java:28) - Computing postfix for the expression: 12 3 /
4.0

D:\JavaDevelopment\Testing\ForumQuestions3\Security>MORE

Also the posted notes on executing the programs has a different name than the zip file:
second-external.zip vs second-internal.zip

That was a mistake on my part. You got those names right in the run.

Here's what I get in the console when I run the zip files. What is the first one supposed to do? Why is it trying to get permissions?

The second one works because all the dependencies have been unjarred and copied to the new JAR file and hence it has the same effect as that of having the entire Log4j source code in your own project (and thereby its class files in the JAR).

The first one doesn't work because the Eclipse utility class attempts to read the Manifest file, read the JAR files packaged in the JAR file and add them to the classspath of my Postfix calculator. Since all this isn't done by default by the `java` process but our custom code, the security exception is thrown. What kind of policy file are you using? If you don't give it even the "read" permissions, I don't think the first approach would work out.

What read permissions does it need?
The first time I tried running the first zip file I got a permission exception which I permitted with this:
permission java.lang.RuntimePermission "setContextClassLoader";
The next execution is the one I posted the console for.

As already mentioned, the first zip file does a lot of extra things:

  • Read the manifest file programatically
  • Create new URL classloaders with the URL being the JAR url
  • Retrieve the main class using reflection and invoke the `main` method on it

Anyways, you really need not run the first zip. There is absolutely no difference between the two JARs code wise. The first JAR was uploaded so as to show the extra classes present in that JAR which are used for dynamically setting the classpath based on nested zips. Trying out the same in Eclipse should give you a a better picture.

Sorry I don't have an IDE.

to show the extra classes present in that JAR which are used for dynamically setting the classpath based on nested zips

That is the part I was interested in seeing.

That is the part I was interested in seeing.

I don't have the source code for those since they are pre-packaged with the standard eclipse distribution. If you are still curious, you can try:
1) decompiling the classes using a decompiler like JAD
2) Google for the classes present in the org.eclipse.* package structure and you would surely stumble upon a link to the source.

Hope that helped.

Thanks for the info.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.