Question

I have written an application in Java and succesfully compiled it using gcj. It worked surprisingly well, but I've run into a hurdle: I can only run the executable through a shell script, because I have to specify the library paths.

The libraries I need are SWT, Xerces and GNU-crypto.

Is there a way to statically link the libraries when compiling in gcj, or is this not a good idea? Alternatively, can I specify the (relative) library path while compiling?

Presently, my shell script looks like this:

#!/bin/sh
export LD_LIBRARY_PATH=./libs/:$LD_LIBRARY_PATH
exec ./MyJavaApp $*
Was it helpful?

Solution

The idea is to make the static field "sys_paths" null so that it would construct the paths from the changed value. See the post here (Post#223 by AjaySingh516) http://forums.sun.com/thread.jspa?messageID=3744346#3744346

Class clazz = ClassLoader.class;
Field field = clazz.getDeclaredField("sys_paths");
boolean accessible = field.isAccessible();
if (!accessible)
    field.setAccessible(true);
Object original = field.get(clazz);
// Reset it to null so that whenever "System.loadLibrary" is called, it
// will be reconstructed with the changed value.
field.set(clazz, null);
try {
    // Change the value and load the library.
    System.setProperty("java.library.path", "./libs/");
    System.loadLibrary("mylibapr");
} finally {
    // Revert back the changes.
    field.set(clazz, original);
    field.setAccessible(accessible);
}

.

gcj System Properties (See: Standard properties supported by libgcj)

http://gcc.gnu.org/onlinedocs/gcj/System-properties.html

.

Solution#2 : Set System environment variable at compile time

http://linux.die.net/man/1/gcj

For this you have to use parameter -Djava.library.path=./libs/ with gcj

From gcj manual (above link):

--main= CLASSNAME

This option is used when linking to specify the name of the class whose "main" method should be invoked when the resulting executable is run.

-Dname[=value]

This option can only be used with "--main". It defines a system property named name with value value. If value is not specified then it defaults to the empty string. These system properties are initialized at the program's startup and can be retrieved at runtime using the "java.lang.System.getProperty" method.

I have never worked with gcj but as per docs these system properties can be retrieved at runtime, hence it will be portable to other systems as well.

Also see: http://gcc.gnu.org/wiki/Statically_linking_libgcj?action=show&redirect=Statically+linking+libgcj

OTHER TIPS

To answer the first part of your question -

From the gcj man page: "Static linking of libgcj may cause essential parts of libgcj to be omitted. Some parts of libgcj use reflection to load classes at runtime. Since the linker does not see these references at link time, it can omit the referred to classes. The result is usually (but not always) a "ClassNotFoundException" being thrown at runtime. Caution must be used when using this option."

For the static linking of the other libraries, I'm not sure. I haven't had a reason to do that.

Linux executables are different than Windows. Normally you have a "launcher" or some such depending on which exact windowing system you are using. You set the icon in that, not on the executable itself. Usually, launch scripts are used to set any environment that you need for running the executable. Again, this all depends on your exact desktop window system.

Why are you using an AOT? I would suggest reading the following article. One of the drawbacks that it mentions for AOTs is the following...

Dynamic applications. Classes that the application loads dynamically at runtime may be unavailable to the application developer. These can be third-party plug-ins, dynamic proxies and other classes generated at runtime and so on. So the runtime system has to include a Java bytecode interpreter and/or a JIT compiler.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top