Java 9 third-party module « linking », how?, when? -> java.lang.NoClassDefFoundError - java

Please do not provide solutions using Maven, Gradle… I look for a CLI solution only. No jlink-based solution as well.
Given Open_My_type_module-1.0.jar as a preexisting compiled Java 9 module:
module Open_My_type_module { // module-info.java
exports Open_My_type_package;
opens Open_My_type_package;
}
The code in this module only declares the following class:
Open_My_type_package.My_type
I reuse this module into another one as follows:
module Access_My_type_module { // module-info.java
requires Open_My_type_module;
}
// Business code (for test only in a Main.java class):
Class<Open_My_type_package.My_type> c = Open_My_type_package.My_type.class;
Starting from the following structure:
THIRD_PARTY_MODULE >> Open_My_type_module-1.0.jar
src >> main >> java >> com >> X >> Access_My_type_package >> Main.java
src >> main >> java >> module-info.java
Compilation succeeds based the following line:
javac -d PRODUCTION_SOFTWARE --module-path THIRD_PARTY_MODULE src/main/java/com/X/Access_My_type_package/Main.java src/main/java/module-info.java
Next, before execution, I package my software as follows:
cd PRODUCTION_SOFTWARE
jar --create --verbose --file Access_My_type_module-1.0.jar --main-class com.X.Access_My_type_package.Main *
Packaging DOES NOT seem to « link » Open_My_type_module-1.0.jar in the final executable, but I check the inside of the packaged software:
jar --file=Access_My_type_module-1.0.jar --describe-module
Display (everything seems sound):
Access_My_type_module jar:file://./Access_My_type_module-1.0.jar/!module-info.class
requires Open_My_type_module
requires java.base mandated
contains com.X.Access_My_type_package
main-class com.X.Access_My_type_package.Main
Finally, execution fails with java.lang.NoClassDefFoundError from:
java --module-path THIRD_PARTY_MODULE -jar Access_My_type_module-1.0.jar
I believed that --module-path THIRD_PARTY_MODULE is enough to link Open_My_type_module-1.0.jar at execution time, but I keep the feeling that my packaging command is shaky. Beyond, I’m sure I’ve missed of a key issue about Java 9 modules… HELP WELCOME please!

Solution (below) is inspired from https://sites.google.com/a/athaydes.com/renato-athaydes/posts/guidetojava9-compilejarrun.
With Java modules, execution is better controlled using --module instead of -jar. So
java --module-path THIRD_PARTY_MODULE --module Access_My_type_module works fine!
Assumption: Access_My_type_module-1.0.jar must be located within THIRD_PARTY_MODULE along with Open_My_type_module-1.0.jar (for simplicity here). In short, java finds in the THIRD_PARTY_MODULE directory all the desired stuff.
Please note that --module required the module name (ie, Access_My_type_module) and
NOT the jar file name!
Please also note that Access_My_type_module-1.0.jar manifest has already been set up with a main class at packaging time... if not tell java which is the main class at execution time.

Related

Java packages: no class def found

so I've tried many of the solutions that are present in this website but none could help me.
The problem:
I have my project files structured like this:
cnv/webserver/aplication/insProj.java
cnv/webserver/aplication/IntFactorization.java
and both are in the package webserver.aplication.
to compile and run i do this:
starting at the folder cnv and with the $CLASSPATH=/home/ll/Documents/cnv
cd webserver/aplication
javac -source 1.4 insProj.java
javac IntFactorization.java
cd ..
cd ..
java -XX:-UseSplitVerifier webserver.aplication.insProj ./webserver/aplication/IntFactorization.class
java -XX:-UseSplitVerifier webserver.aplication.IntFactorization 5
When executing this last instruction, it returns an exception:
Factoring 5...
Exception in thread "main" java.lang.NoClassDefFoundError: webserver.aplication.insProj
at webserver.aplication.IntFactorization.calcPrimeFactors(IntFactorization.java:22)
at webserver.aplication.IntFactorization.main(IntFactorization.java:59)
The instrumentations i'm making is incrementing a counter when a given method is executed and creating a file when the class ends execution. I know this works because i've tested outside these packages and it works fine.
It seems BIT doesn't work well with packages. In the end, I removed insProj from any package and inserted its folder in the classpath. Then it began to work.

Using UMLGraph to generate single dot file for multiple java classes

How can I ask UMLGraph to generate a single diagram for all the underlying .java classes within a package ?
I am using UMLGraph along with Graphviz to generate a .png UML diagram file.
The command that I am running to geenrate a.dot file is :
java -jar C:/Program Files/Java/jdk1.7.0_80/lib/UmlGraph.jar -all -private A.java
This runs succesfully to geenrate a .dot file.
However,I wish to create a single UML diagram out of them ( They are all linked to eachother via java code).
The "uml-parser-test-1" (folder/package) contains all about 5 .java files and for that I am running
C:/Users/xyz > java -jar "C:/Program Files/Java/jdk1.8.0_60/lib/UmlGraph.jar" -all -private "D:/xyz/abcd/uml-parser-test-1/"
When I run above code , I get an error : UMLGRAPH ERROR - ILLEGAL PACKAGE NAME
Where am I going wrong
**EDIT:: 6th Oct**
There was an issue with umlgraph.jar path and I had corrected it. Thanks for pointing that out.
Now I am able to run the command you suggested without any errors. THe thing is my "Persons" package(folder) contains 4 java files(A,B,C,D.java). When I run the command, it generated .dot file on the command line and not in my file system.Moreover, it is incomplete as there is no information about classes :
Below is the trace of my command line .
C:\Users\xyz>java -classpath "C:/Program Files/Java/jdk1.8.0_60/lib/UmlGraph.jar;C:/Program Files/Java/jdk1.8.0_20/lib/tools.jar" org.umlgraph.doclet.UmlGraph -package -output - -sourcepath "C:/Program Files/Java/jdk1.8.0_60/lib/Persons" org.umlgraph.doclet
Loading source files for package org.umlgraph.doclet...
UmlGraph: warning - No source files for package org.umlgraph.doclet
Constructing Javadoc information...
UmlGraph: warning - No source files for package org.umlgraph.doclet
UMLGraph doclet version R5_7_2-3-gee82a7 started
Building general class diagram
#!/usr/local/bin/dot
#
# Class diagram
# Generated by UMLGraph version R5_7_2-3-gee82a7 (http://www.umlgraph.org/)
#
digraph G {
edge [fontname="arial",fontsize=10,labelfontname="arial",labelfontsize=10];
node [fontname="arial",fontsize=10,shape=plaintext];
nodesep=0.25;
ranksep=0.5;
}
2 warnings
Any idea, why it is not parsing the class details?
You must specify in the command line invocation the package name and the directory where its source code is located. The following example, when run in the UMLGraph directory, generates a diagram for the UMLGraph classes.
java -classpath "lib/UmlGraph.jar;C:\Program Files\Java\jdk1.8.0_20/lib/tools.jar" org.umlgraph.doclet.UmlGraph -package -output - -sourcepath src/main/java org.umlgraph.doclet | dot -Tpng -oumlgraph.png

Java Classpath error-cannot find my class

I am trying to use randoop(automatic test generator for Java) and randoop cannot find my class:
eliezer#ubuntu:~/Desktop$ java -ea -classpath \
randoop.1.3.2.jar:home/eliezer/myclasses \
randoop.main.Main gentests \
--testclass=/home/eliezer/Desktop/myclasses/ArrayListError
policy = sun.security.provider.PolicyFile#85af80
Throwable thrown while handling command:java.lang.Error:\
classForName(/home/eliezer/Desktop/myclasses/ArrayListError)
java.lang.Error: classForName(/home/eliezer/Desktop/myclasses/ArrayListError)
at randoop.util.Reflection.classForName(Reflection.java:206)
at randoop.util.Reflection.loadClassesFromList(Reflection.java:386)
at randoop.main.GenInputsAbstract.findClassesFromArgs(GenInputsAbstract.java:507)
at randoop.main.GenTests.handle(GenTests.java:184)
at randoop.main.Main.nonStaticMain(Main.java:80)
at randoop.main.Main.main(Main.java:42)
Caused by: java.lang.ClassNotFoundException: \
/home/eliezer/Desktop/myclasses/ArrayListError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:186)
at randoop.util.Reflection.classForName(Reflection.java:198)
... 5 more
Randoop failed.
Last sequence under execution:null
My class is called ArrayListError.java and is found in /home/eliezer/Desktop/myclasses.
The randoop docs are found at: https://randoop.github.io/randoop/manual/index.html.
I am sure it is something really trivial but I'm inexperienced with these things.
You need to set your classpath such that, jvm should be able to locate all your resources like classes, files, jars etc.
In your case, ArrayListError is placed under directory /home/eliezer/Desktop/myclasses. You need to place this in your classpath.
Once you point your classpath to mentioned directory, You need to pass the class name to --testclass=ArrayListError.
java -ea -classpath randoop.1.3.2.jar:/home/eliezer/Desktop/myclasses randoop.main.Main gentests --testclass=ArrayListError
should fix your problem. I suggest you to search on setting classpath and read on.
This is wrong
my class is called ArrayListError.java and is found in
/home/eliezer/Desktop/myclasses.
Your ArrayListError.java is the source code, but java virtual machine needs a compiled class in its classpath.
EDIT:
Since you said that you have the .class file also, then your problem can be solved in two ways
a. No package
Run the command (take care of the --testclas, it is not directory, it should be the class)
java -ea -classpath randoop.1.3.2.jar:/home/eliezer/myclasses
randoop.main.Main gentests --testclass=ArrayListError
b. Class in a package
If your ArrayListError does have package com.test; make a directory /com/test in your myclasses directory and run the command below
java -ea -classpath
randoop.1.3.2.jar:/home/eliezer/myclasses/com/test/ randoop.main.Main
gentests --testclass=com.test.ArrayListError
Check your classpath on the command line;
I see home/eliezer/myclasses, without the leading /.

Receiving "wrong name" NoClassDefFoundError when executing a Java program from the command-line

I have a problem while trying executing my java application.
Whenever I try to execute the program through the command
java ProgAudioJ
I get this error:
Exception in thread "main"
java.lang.NoClassDefFoundError: ProgAudioJ (wrong name: es_2011/ProgAudioJ)
at java.lang.ClassLoader.defineClass1(NativeMethod)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
at java.security.AccessController.doPrivileged(NativeMethod)
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)
Could not find the main class: ProgAudioJ. Program will exit.
If I remove from my code:
package es_2011;
Everything works perfectly. How do I solve the problem?
Because I found these answers unclear, here is what you need to do.
First, if you package your code (IE your classes have the package keyword at the top) the compiled classes have to be in a directory with the same name as your package declaration in code. After you have compiled your classes, you need to move up a directory when you exectute the java command, and you include the name of the package. For example, if your code exists in /myFolder/myPackage/ , and your class starts with package myPackage (note that the directory and the package are the same name), then you would do the following (linux / osx):
cd /myFolder/myPackage
javac MyClass.java
cd ..
java myPackage.MyClass
Edit - A late edit to clarify something I see people get confused on. In the example above, the package is only one deep, meaning its just myPackage. If you code has a larger package, like
package com.somedomain.someproject;
you will need to execute the java command from the directory which contains the root directory for that package. For example if your compiled code is in myCode/com/somedomain/someproject/MyMainClass.class, then you will execute the java command from the myCode folder, like this (Again, take special note that the directory structure is the same as the package declaration):
cd /myCode
java com.somedomain.someproject.MyMainClass
Try using:
java es_2011.ProgAudioJ
(instead of java ProgAudioJ).
I'm making some assumptions here about your current working directory and your CLASSPATH. If you can provide information about the command you're running (e.g. what directory you're in, where the class file is located, etc.), we can help you more efficiently.
Try this (compile and run):
dir
2011-02-10 00:30 <DIR> .
2011-02-10 00:30 <DIR> ..
2011-02-10 00:27 58 es_2011
javac es_2011/ProgAudioJ
java es_2011.ProgAudioJ
It's quite clearly stated there:
java.lang.NoClassDefFoundError: ProgAudioJ (wrong name: es_2011/ProgAudioJ)
If you want to put a class in a package(*), then the source code must be placed in a corresponding directory, e.g.,
src/Main.java <- root package (no declaration)
src/es_2011/ProgAudioJ.java <- package es_2011;
(*) You should do it always, except for tiny throw-away stuff and possibly for the main class.
Try this,
Compile your class using below command
$ javac ProgAudioJ.java -d .
Run your application by command
$ java es_2011.ProgAudioJ
The reason that it works when you remove
package es_2011
is that you are changing how the compiler packages up, and effectively locates, the file.
I had the same problem - and the error message wrong name: does indeed point you to the answer. You are using the wrong name "ProgAudioJ" in order to run the .class file.
It has been packaged up as
es_2011/ProgAudioJ
In order to run it - you have to either move up a directory:
If you are here: (Windows)
src\es_2011\
move to
src\
Then run the line:
java es_2011.ProgAudioJ
This tells the compiler to look for the ProgAudioJ - which resides in the es_2011 package. For a standard installation, this will be based on folders - so it will look for the es_2011 folder first, and then the name of the .class file that you want to run (ProgAudio).

Why can't I load this class file in Rhino console?

I'm prototyping a web page scraper using Rhino and Env-js. Nevermind that the documentation for both projects is atrocious... I'm trying to load up the File.java example class that is supplied with Rhino. For simplicity sake, I've got File.java, js.jar, jline.jar and env.rhino.1.2.js all in one directory. I've tried specifying the current directory using the classpath command line option, but still whenever I call defineClass("File") I get an error saying the class file isn't found. What am I doing wrong here??
$ ls -1
File.java
env.rhino.1.2.js
jline.jar
js.jar
$ java -cp .:js.jar:jline.jar jline.ConsoleRunner org.mozilla.javascript.tools.shell.Main -opt -1
Rhino 1.7 release 2 2009 03 22
js> defineClass("File")
js: "<stdin>", line 2: Class "File" not found.
at <stdin>:2
Don't you need to compile File.java before using it, as the classpath "." only makes sense if it contains some compiled class in it?

Categories

Resources