Manual JAR compilation for Scala & Kotlin - java

I'm trying to create a proof of concept for Kotlin calling Scala code.
Here's what the project looks like at the moment:
kotlin-src/
hello.kt
scala-src/
Hello.scala
Then to compile both languages:
kotlinc kotlin-src/*.kt
scalac scala-src/*.scala
Which produces the following files in the root directory:
META-INF/
main.kotlin_module
HelloKt.class
HelloScala.class
That I attempt to turn into a JAR with:
jar cvfM run.jar *.class META-INF
However, it won't run (and I assume it's because I'm not specifying a main class).
$ java -jar run.jar
Error: Invalid or corrupt jarfile run.jar
So, I've created the following manifest:
Main-Class: HelloKt
Before compiling the jar, this file gets copied into the META-INF directory and the structure of the resulting jar is as follows:
HelloKt.class
HelloScala.class
META-INF/
META-INF/main.kotlin_module
META-INF/MANIFEST.MF
The new JAR will execute, but always fails with a runtime exception.
$ java -jar run.jar
Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics
at HelloKt.main(hello.kt)
Caused by: java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 1 more
What are the remaining steps needed to get the JAR compiled and running the main method in the Kotlin class?
Are there runtime classes that need to be bundled with the Scala/Kotlin code to make this work?

I haven't tested it, but it should work:
Compile your code as you have
Download kotlin-stdlib jar from Maven Central
Verify that you used the same version of the stdlib while compiling
Add directory with the stdlib jar to the classpath parameter of the java command when running the jar

Related

Error: Could not find or load main class when trying to run jar file

I'm trying to create a JAR file of my Java code. There are four classes - A.java, B.java, C.java, and D.java. A.java has the main method. These are in a folder called src, and my manifest file is outside of src, and all of my .class files are in bin which is inside src. I created a MANIFEST.MF with the following contents:
Manifest-Version: 1.0
Main-Class: src/A
I then use the command jar cmf MANIFEST.MF A.jar src/bin/*.class src/GraphFile.txt src/ProblemA.txt src/ProblemB.txt (there are a few text files I need to include as well in my JAR file). Then, when I run java -jar A.jar ProblemA.txt GraphFile.txt (note that ProblemA.txt and GraphFile.txt are input files that my program accepts and uses), I get the following error:
Error: Could not find or load main class src.A
Caused by: java.lang.ClassNotFoundException: src.A
Can anyone explain what I am doing wrong or any steps I am missing? Unfortunately, I cannot post the actual code because this is for a class project, but I just need to get it compiled into a JAR file for submission! Thanks for any help.

Java Classpath NoClassDefFoundError During Runtime

I am coming back to Java after quite some time. Having a little trouble with classpath. Would really appreciate it if someone could please point me in the right direction!
My folder structure is as follow:
├── lib
│ └── algs4.jar
└── src
└── HelloWorld.java
HelloWorld.java
import edu.princeton.cs.algs4.StdOut;
public class HelloWorld {
public static void main(String[] args) {
StdOut.println("Hello World");
}
}
I compiled my program with the following cmd
cd src
javac -cp ../lib/* HelloWorld.java
However, when I run my program using java HelloWorld, I get the following error.
Exception in thread "main" java.lang.NoClassDefFoundError: edu/princeton/cs/algs4/StdOut
at HelloWorld.main(HelloWorld.java:5)
Caused by: java.lang.ClassNotFoundException: edu.princeton.cs.algs4.StdOut
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
I dont understand how it compiles fine, but then its unable to find classes at runtime. Could someone please shed some light on this ? Thank you in advance!
It was painful, but I finally fixed it. Turns out when running the program, you not only have to specify the location of the JAR files, but you also have to specify the location of your own file. (Seems obvious now >.<)
For example, in my case, running the following is not good enough.
java -cp ../lib/* HelloWorld
We included the the JARs but didn't include the folder that actually contains HelloWorld.class.
To fix this, I had to run the following. We are including the location of the JAR and the location of the file being executed.
java -cp ../lib/*:. HelloWorld
(Some of you might have to escape * depending on your OS / shell settings)
To execute your program you also need to pass the classpath to the java command like this.
java -cp ../lib/* HelloWorld
When you've compiled your code you told the compiler to use the ../lib/* directory(and files) to look up for class definitions, of course, the compiler found them, and write the byte code in the HelloWorld.class file but this bytecode only contains your code (the lines you wrote in HelloWorld.java) for any external library you use there the compiler will only store a sort of reference with the full package name and the method name. No bytecode from the jar will be stored in the HelloWorld.class file.
So to execute HelloWorld you need to tell the JVM to load first all the external classes that you in the code passing them with the -cp parameter.
Then, the JVM will execute your code, look for the reference to the jar code via package/method name and execute them.
If you don't provide -cp ../lib/* the JVM will load only the standard library (All the classes in JDK) and your HelloWorld.class thus it won't find the external jar in memory.

Getting Error: Could not find or load main class while opening executable Jar file

I'm opening fontawesomefx-glyphsbrowser-all-1.0.jar
Using java -jar /home/ubuntu/Downloads/fontawesomefx-glyphsbrowser-all-1.0.jar but getting error
Could not find or load main class
Also tried :
java -cp /home/ubuntu/Downloads/fontawesomefx-glyphsbrowser-1.3.0/lib/fontawesomefx-glyphsbrowser-1.3.0.jar de.jensd.fx.glyphs.browser.GlyphsBrowser
and getting:
Error: Could not find or load main class de.jensd.fx.glyphs.browser.GlyphsBrowser
Caused by: java.lang.NoClassDefFoundError: javafx/scene/layout/VBox
Another try:
java -jar fontawesomefx-glyphsbrowser-all-1.0.jar
Error: Could not find or load main class de.jensd.fx.glyphs.browser.GlyphsBrowserApp
Caused by: java.lang.NoClassDefFoundError: javafx/application/Application
JavaFX is no longer packaged with JDK but I think it is from JDK 11 and I'm using JDK 8 so why I'm getting Caused by: java.lang.NoClassDefFoundError: javafx/application/Application
I'm using open-jdk 8.0
So how to do?
The 'main class not found' error comes in 2 cases:
Manifest.MF file of the .jar package does not contain a valid 'Main-Class' attribute. This can happen due to the .jar file not being created correctly. This is mostly a bug with the creation of jar file.
The Jar file is meant to be used as a library, but not as an executable program and therefore, it does not contain any class with 'main' method.
For case # 1 (bug in manifest.mf), these are the possible workarounds / fixes:
Ask the provider of jar file to create it again with proper 'Main-Class' definition in the manifest.mf file
Extract the contents of jar file to a directory, add 'Main-Class' attribute to manifest.mf file and package the folder into jar again.
Here is an article from Oracle on how the manifest.mf file can be updated:
https://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html
i managed to fix this problem by using Oracle JDK 8.

CMake add_jar with INCLUDE_JARS not working

I am using CMake to compile jar file with add_jar command. Problem is that when I try to add INCLUDE_JARS to specify dependency to external jar, the code will not run. Here is the code example:
add_jar(testJar
SOURCES
sources/com/test/Main.java
INCLUDE_JARS
${CMAKE_SOURCE_DIR}/extern/org.json/json-20171018.jar
ENTRY_POINT com.test.Main
)
Running the testJar with "java -jar testJar.jar" gives me the following error:
Exception in thread "main" java.lang.NoClassDefFoundError: org/json/JSONException
The org.json jar should be in classpath, right? Adding manifest file with classpath solves the problem but is there way to do this without the manifest file?
And yes, I would use maven or gradle for building but as of restrictions in the project I cannot do that :)
The option INCLUDE_JARS only makes sure that the given external jar is added to the class path upon compilation of the given Java source files. The jar file is neither copied to the build directory nor is it added to the jar file generated by add_jar.
If inclusion of the external jar in the Manifest file is not an option for you, manually add it to the class path upon running the testJar, i.e.:
java -cp path/to/json-20171018.jar -jar testJar.jar

Getting "java.lang.NoClassDefFoundError" on running with javaagent

I am trying to instrument a jar file (main.jar) with javaagent.jar using BCEL. basically where ever I find any aload in bytecode, I m trying to insert a function call to a static function called Fun() in class "someclass" using
if (opcode instanceof aload) {
iFactory.createInvoke("someclass", "fun", Type.VOID, new Type[]{}, Constants.INVOKESTATIC);
my "someclass" class reside in javaagent.jar
on executing
java -javaagent:javaagent.jar -jar main.jar
or
java -javaagent:javaagent.jar -jar main.jar javaagent.jar
or (I created a separate jar for my "someclass" called someclasscontained.jar)
java -cp someclasscontained.jar -javaagent:javaagent.jar -jar main.jar
I am getting
Exception in thread "main" java.lang.NoClassDefFoundError: someclass
error. i tried with -bootclasspath/p option but still not working. does anyone has any clue?
(1) all jar resides in same folder
2) this question may be similar to one question but solution is not correct/satisfactory for that question so please don't mark it duplicate )
If someclass is defined in a different jar file, you need to add it to the Boot-Class-Path list in your agent jar manifest file:
some.jar -> contains someclass.class
javaagent.jar -> contains your instrumenting classes and MANIFEST.MF file
MANIFEST.MF file should contain line like
Boot-Class-Path: javaagent.jar some.jar

Categories

Resources