Update Mar 20: The gcj is currently unlikely to work. GCJ's CVS is in such an unstable state that it's impossible to follow them. Tasks to be done: update eh.c and get rid of interface hacks since the new gcj uses kaffe's interface dispatch scheme as well. -------------------------------- Documentation about the Kaffe/GCJ integration. By Godmar Back <gback@cs.utah.edu>, Nov 29, 1999 The Kaffe/GCJ integration is at this point 95% complete. Here's a list of the remaining limitations/problems: - exception dispatch is not thread-safe - deadlock in AWT and javac. - static synchronized methods are probably not handled properly. - it's x86 only at this point. - floating point exceptions do not work properly on x86. - setjmp/longjmp based exceptions not supported. - linker scripts for native aliases not implemented, awaiting libtool fix. - disregards order of class files in classpath when shared objects are included. - fixup only supports a single module. Need scripts. - only supports dlopen-style dynamic linking. I know this sounds horrible, but I'd still claim we're at 95% completion. What are the goals of the kaffe/gcj integration? One overriding priority when doing this work was to accomplish it in a way that would allow a *stock gcj installation* to be used to build shared object files that could be used with Kaffe. I believe it would have been unacceptable for people to have to have multiple gcj installation around. On the other hand, we do not see kaffe as a libgcj replacement or competitor. While there may be overlap, they have different goals. Gcj support in kaffe requires you to have libgcj installation on your machine when you build kaffe. (Pre-installed versions of kaffe do not require this just to run gcj-compiled code.) A second goal was to be able to arbitrarily mix and match precompiled and just-in-time compiled code. *Any* class in the system can be either precompiled or just-in-time compiled, and they should interact seemlessly. Because I considered changing gcj a taboo, I used what I call a surrogate-based approach. For each run-time object that describes a class, method or field that gcj code expects, there exists a surrogate kaffe object that describes the very same class, method, or field. Here's a picture: |----------| |---------| |GCJ class | <--- ------> | Kaffe | | | \ / | class | | | X | (valid | | | / \ | data) | |GCJ2KAFFE | ----- ------ | gcjPeer | |----------| |---------| java::lang::Class struct Hjava_lang_Class The GCJ2KAFFE macro (ab)uses the "thread" field in java::lang::Class to hold a pointer to its kaffe surrogate class. Similarly, a class's method, field, interface, and dispatch table are created from their gcj counter parts. A constant pool is not created, instead, processing of constants done directly from the GCJ class object. To ensure consistency, we directly include GCJ header files in some files in the gcj/ subdirectory. We communicate between those files and the files that include Kaffe's headers by using basic types such as int or char *. For instance, a GCJ utf8const is passed as a const char* to the kaffe code where a Kaffe utf8const is created. To be continued.... How do I use kaffe/gcj? You first have to compile your .java (if gcj supports it) or your .class files against Kaffe's class libraries. To do that, you need to create an uncompressed jar file with Kaffe's class libraries, or extract these class libraries in a directory. Directly using Kaffe's Klasses.jar does not currently work cause gcj does not support compressed jar files. Then you have to build a shared module. Example: gcj -g -fPIC -c -classpath .:....kaffeclasspathlocation.... X.class gcc -shared -o X.so X.o Be sure to specify Kaffe's class libraries when compiling, or else gcj will pick up libgcj.zip, which is incompatible. Be sure to link with gcc, not gcj, to avoid using libgcj's spec file. Next, you need to create a so-called fixup module. To do this, compile and run the program fixup.c in developers. Example: ....fixup X > _fixup_X.cc g++ -fPIC -Ilibgcj_include_dir -c _fixup_X.cc gcc -shared -o _fixup_X.so _fixup_X.o Note: the prefix "_fixup_" is currently hardwired. For every shared module X.so, there has to be _fixup_X.so module in LD_LIBRARY_PATH. Next, include X.so in your classpath and run it: setenv CLASSPATH X.so kaffe X That's it. How do I compile Kaffe's class libraries? First, make sure that you've compiled them with jikes, not with kjc. Kjc generates correct code that gcj rejects. You can compile the class libraries as individual files. I recommend using the -w option to turn off warnings, or else gcj will warn you about unreachable bytecode jikes generates in almost every file. I've been using -O3. I believe that more options need to be specified in order to get full inlining of private methods. (-finline-functions?) There have been some problems with inlining that the gcj crew addresses. There have been some other problems which have been addressed in gcj versions more recent than Dec 14 (see developers/GCJ.notes.1) Note that fixup currently patches up all external symbols. For this reasons, we really only support one big shared module. So if you want precompile your app *and* the library, you have 1. first create .o files for all .class files 2. link all these .o files into one big .so 3. invoke fixup on the .so creating two .so files and fixing them up separately will probably not work at this time.