Why doesn't GCJ find the classes from my imported packages? - java

I want to compile a small Java application to a Windows executable.
The application is very small, only a single main class, but it uses Apache POI.
When I compile it, everything works fine, as long as I put the POI Jar into the class path argument.
But when it comes to linking, GCJ cannot resolve the references the classes in the POI package. The messages are all like this:
undefined reference tp 'org::apache::poi:hssf:usermodel:HSSFWorkbook::class$'
What do I have to do in order to link my application?

You have to compile the imported Jars into .so libraries separately. Make sure to provide the Jars in the --classpath, both while compiling the libraries as while compiling your code.
An example, where I'm compiling the GNU crypto library:
gcj --classpath=source/:libs/gnu-crypto.jar -fjni -c libs/gnu-crypto.jar -o libs/gnu-crypto.o
gcj -shared -fPIC -o libs/libgnu-crypto.o libs/gnu-crypto.o -o libs/libgnu-crypto.so
Finally, execute your executable through a shell script referencing the library path. For example:
#!/bin/sh
export LD_LIBRARY_PATH=./libs/:$LD_LIBRARY_PATH
exec ./MyJavaApp $*

Related

How do I use a library on a exported runnable jar?

I've got a java script that uses OpenCV 4.6.0 to modify some pics. I use Eclipse to edit the java project. I downloaded the OpenCV library (a opencv_460.jar file) which is used inside Eclipse. When I run the code, it works just fine. So I export the java project as a runnable jar.
The thing is that I want to use the jar on a different machine (ubuntu 18.04). When I run java -jar TheExportedJar.jar, I get the following error:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no opencv_java460 in java.library.path: /usr/java/packages/lib:/usr/lib/x86_64-linux-gnu/jni:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/usr/lib/jni:/lib:/usr/lib
I installed OpenCV 4.6.0 on the machine using CMake
wget -O opencv.zip https://github.com/opencv/opencv/archive/4.6.0.zip
unzip opencv.zip
mkdir opencv-4.6.0/build
cd opencv-4.6.0/build
cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local -D BUILD_PKGCONFIG=ON ..
make -j$(nproc)
sudo make install
The version is ok, everything looks fine, except it doesn't actually get installed. Things that should exist, like alternative path /usr/local/lib/pkgconfig/opencv4.pc, don't actually exist
How does java work? Why can Eclipse use a jar as a library, but I can't once the project is packed? Is there a way to skip the installation process (as every type of install I've tried was just a waste of time) and import a jar from a specified path as a library inside the java code?
What other solutions could there be?

How to include dependency jar files into jar file

I'm build a jar file with code that uses other jar files as dependencies, and I can't get it to run (I keep getting a NoClassDefFoundError).
All the other similar issues I could find online used maven as a solution, which I want to avoid doing. When I run my code like this:
#!/bin/bash
java -cp "src/.:src/jsoup-1.9.2.jar:src/commons-cli-1.3.1.jar" WikipediaWords $#
it runs fine, but when I try:
java -cp "src/.:src/jsoup-1.9.2.jar:src/commons-cli-1.3.1.jar" -jar WikipediaWords.jar $#
it complains.
I compile my jar file with all the dependencies inside, though, so I really have no clue why it can't find anything. Ideally, I wouldn't even want to have to add the -cp path to my java execution, and just have the jar file know to use the nested jar dependency files.
If you have any clue about how to solve this (run the jar file without class def error) without the use of Maven, please let me know!
Thanks in advance!
P.S. My building code might be of use:
#!/bin/bash
javac -cp "src/.:src/jsoup-1.9.2.jar:src/commons-cli-1.3.1.jar" src/WikipediaWords.java
jar cfm src/WikipediaWords.jar src/Manifest.txt -C src/ .
Try running the below command:
java -cp "src/.:src/jsoup-1.9.2.jar:src/commons-cli-1.3.1.jar:WikipediaWords.jar" WikipediaWords $#
OR
java -cp "WikipediaWords.jar:src/.:src/jsoup-1.9.2.jar:src/commons-cli-1.3.1.jar" WikipediaWords $#

building c++ code into a shared library

I have some c++ code which i use as shared library in a java application.My c++ code uses some libraries like ffmpeg and boost. and ffmpeg libraries in turn depend on libx264. my first question is - can i build my c++ into a "fat" shared library which contains all the symbols from all libraries used so that on a new machine if i just copy the fat .so file everything works.
If thats not possible then can you help me fix my current build process. This is what i am doing currently -
1)on a local VM(ubuntu 64) i compile ffmpeg code using -fPIC flag and install h264 and boost using apt-get commands.
2) on the same VM i compile my code using make file which looks like this-
INCLUDES = -I/opt/ffmpeg/include -I/usr/lib/jvm/java-7-openjdk- amd64/include -I/usr/lib/jvm/java-7-openjdk-amd64/include/linux
LDFLAGS = -L/home/ubuntu/ffmpeg_shared
LIBRARIES = -lavformat -lavcodec -lswscale -lavutil -lpthread -lx264 -lboost_system -lboost_thread -lboost_chrono
CC = g++ -std=c++11 -fPIC
all:clean final
final:Api.o ImageSequence.o OverlayAnimation.o Utils.o ImageFrame.o
$(CC) -o final.so Api.o ImageSequence.o OverlayAnimation.o Utils.o ImageFrame.o $(LDFLAGS) $(LIBRARIES) -shared
3) on a new machine where java app will run. i install h264 and boost using apt-get commands and copy ffmpeg's compiled library files to /usr/local/lib.
4) copy the final.so file to this new machine. but when the java code tries to use the final.so file i see it tries to use wierdly named files. for example - it tries to find libavcodec.so.57 , libavformat.so.57 etc. to fix this i just created a copy of these files ie libavcodec.so copied to libavcodec.so.57.
5)But these ffmpeg libraries in turn uses a differently named lib264.so file. on my new machine the apt-get command for x264 installed a file named libx264.so.148 but one of ffmpeg libraries is searching for file libx264.so.142 even if i rename this libx264.so file i get new errors where ffmpeg libraries tries to call libx264's methods which has these numbers attached.
6) at this time the only working option for me is to bring the c++ code on every new machine and build final.so file locally. this is something i want to avoid since i want to distribute the .so file along with jar file to my clients which they can easily use without having to build and install stuff.
I may have a solution for a 'fat' library, but I'm not 100% sure if it will work.
In general, it is possible to link together static libraries into a shared library by specifying these linker flags.
g++ -Wl,--whole-archive some_static_lib.a -Wl,--no-whole-archive
Therefore you would have to compile all your libraries into static libraries. If you think it's worth the effort to do this, you can give it a try.
To the second part:
It seems that your other machine is using different versions of the libraries. In example libx264.so.148 might be reffering to version 1.4.8 or something like that.
Therefore your libx264.so should be a symbolic link to libx264.so.148. You can verify that with
ln -l
to visualize, where your symbolic link is reffering to.
I recommend to manually compile all needed libraries on both machines. Then these problems should be solved.

Compiling NanoVM Java Virtual Machine

I have problem with compiling NanoVM project from:
http://www.harbaum.org/till/nanovm/index.shtml
NanoVM is Java implementation for AVR microcontrollers. I know this is not efficient. I have problem with "makefile" file. This makefile contains instructions to compile Java .class from source .java files. But i don't know, how can i run makefile? I was using previously javac.exe compiler to write java standard applications. In install instructions writes that I must have Java SDK (J2SE). Is there any difference between SDK and JDK? I have JDK installed, i have read earlier that there isn't any difference between SDK and JDK, but i'm not sure. I know makefile files are used to manage compilation, i previously used makefile to compile programs wrote in C, but is there some Java compiler like gcc? Sorry for my stupid question, i'm quite newbie in makefiles, i think solution is very simple.
My makefile:
#
# Makefile for NanoVMTool
#
APP = NanoVMTool
VERSION = 1.5
all: ../$(APP).jar
CLASSPATH = ../../java/examples
NATIVEPATH = ../../java/native
JAVAFILES = AccessFlags.java CodeInfo.java ConstPoolEntry.java FieldInfo.java \
MethodInfo.java AttributeInfo.java CodeTranslator.java \
ConstPoolEntryError.java InnerClassInfo.java NanoVMTool.java \
ClassFileReader.java CommonInfo.java ConvertException.java \
LineNumberInfo.java NativeMapper.java ClassInfo.java \
Config.java Debug.java LocalVariableInfo.java UVMWriter.java \
ClassLoader.java ConstPool.java ExceptionInfo.java \
MethodIdTable.java Uploader.java NVMComm2.java
# compile target code
$(CLASSPATH)/%.class: $(CLASSPATH)/%.java
javac -classpath $(CLASSPATH):$(NATIVEPATH) $<
%.class: %.java
echo "public class Version {" > Version.java
echo " public static String version = \"V$(VERSION)\";" >> Version.java
echo "}" >> Version.java
javac $<
../$(APP).jar: $(APP).class
jar cmf $(APP).mf ../$(APP).jar *.class
# convert and upload a class file (should be moved to vm/target Makefile)
asuro-%: $(CLASSPATH)/%.class $(APP).class
java $(APP) ../config/Asuro.config $(CLASSPATH) $*
mega8-%: $(CLASSPATH)/%.class $(APP).class
java $(APP) ../config/Mega8.config $(CLASSPATH) $*
clean:
rm -f *.class *~
In order to run a Makefile (on Linux / UNIX), you first need to install "make" and any of the other tools that it uses. In this case, the tools are just the java, javac and jar commands. For the last two, you need a JDK installation.
But i don't know, how can i run makefile?
Change directory to the directory containing the Makefile, then run 'make' with the appropriate target. In this case make all.
Is there any difference between SDK and JDK?
There is no such thing as the Java SDK.
... but is there some Java compiler like gcc?
The Java compiler is javac. That is what your makefile is using.
Sorry for my stupid question, i'm quite newbie in makefiles, i think solution is very simple.
The REAL solution is to find and read a tutorial on Makefiles and how to read, write and use them. (In general, the solution to asking newbie questions is to educate yourself so that you aren't a newbie!)

How do I run a Makefile that was distributed with a Java library?

I downloaded a Java library with a file titled Makefile, but I do not know what to run it with. It has no extension, and this is the text that appears when I open it in TextEdit:
all: BigDecimalMath.jar Wigner3jGUI.jar html
html:
javadoc -sourcepath . -private -d html org.nevec.rjm
BigDecimalMath.jar:
javac org/nevec/rjm/*.java
jar cf $# org
Wigner3jGUI.jar:
javac org/nevec/rjm/*.java
jar cmf Wigner3jGUI.mf $# org/nevec/rjm/*.class
distclean:
rm -rf html *.jar org/nevec/rjm/*.class
Could anyone help me figure out how to run this file (By the way, I have a Mac running Mavericks if that matters at all)
try two commands
make
java -jar Wigner3jGUI.jar
Makefiles are similar to ant files and are run by the make program. I have not seen make used to build jars (usually c/c++). However, it looks like it will build the jars. The all target should build the jars, which can then be run by the java command.

Categories

Resources