[Kde-java] GCJ and qtjava/kdejava

Adam Dingle kde-java@kde.org
Wed, 06 Mar 2002 12:38:58 -0800


I've spent the last few days getting GCJ to work with the qtjava and kdejava 
bindings from the kdebindings package.  I've finally got everything working 
fine, but it took me a while to get there, and so I thought I'd share my 
experiences.  I'm using Red Hat Linux 7.2.

First and foremost: if you want to use GCJ with KDE, you REALLY want to use 
GCC 3.0.4.  I tried several other versions of GCC/GCJ and had trouble with 
all of them, as follows:

- GCJ 2.x doesn't work at all because the qtjava bindings rely on weak 
references and on certain Java utility classes which are present only in GCJ 
3.x.

- When I use GCJ 3.0.1, at least as packaged by Red Hat and distributed with 
Red Hat Linux 7.2, then I can build a Qt program with GCJ, but the program 
hangs almost immediately upon running it.  This is the behavior which Thomas 
Kuhn reported to this mailing list when he tried to use GCJ with qtjava last 
August (see http://lists.kde.org/?l=kde-java&m=99844128813679&w=2).  Thomas 
attributed this hang to JNI problems in GCJ, and I am inclined to agree 
withwhen him.  He worked around the problem by changing some of the qtjava 
code to use CNI, but I've found that using a newer GCJ also solves the 
problem.

- I also tried using a prerelease of GCJ 3.1 from Red Hat's Rawhide 
distribution, the gcc-3.1-0.21 package (OK, I know I was really asking for 
trouble here).  With this GCJ, I was able to built a small Java program that 
used qtjava and my program ran, but crashed on exit.  I spent some time 
debugging and found that the crash occurred in GCJ's JNI runtime code as it 
was freeing local references (see the JNI spec for information about these) 
on exit from my QApplication's exec() method.  I haven't had time to debug 
this more, but I believe that this is either a JNI bug or a bug in GCJ 3.1's 
IdentityHashMap class which the JNI code uses to hold reference counts for 
local references.

But, happily, everything works fine if I use GCJ 3.0.4 (which I had to build 
myself, since I haven't found a Red Hat binary for this GCC anywhere out 
there).  Would GCJ 3.02 or 3.03 work?  I don't know.

Here's some more advice if you want to get this working.  You should compile 
the Java code in the qtjava and kdejava packages to libraries of native code; 
then you won't have to compile that code each time you build your own Java 
applications.  I added the following to 
kdebindings-2.2.2/qtjava/javalib/org/kde/qt/Makefile.am:

GCJ = gcj --classpath=$(CLASSPATH):/usr/share/libgcj.jar
GCJFLAGS = -fPIC -fjni
libqtjavaiface.so: $(EXTRA_DIST)
	 $(GCJ) $(GCJFLAGS) -shared $(EXTRA_DIST) -o $@

And I added the following to 
kdebindings-2.2.2/kdejava/koala/org/kde/koala/Makefile.am:

GCJ = gcj --classpath=$(CLASSPATH):/usr/share/libgcj.jar
GCJFLAGS = -fPIC -fjni
libkdejavaiface.so: $(EXTRA_DIST)
	 $(GCJ) $(GCJFLAGS) -shared $(EXTRA_DIST) -o $@ \ 
-L../../../../../qtjava/javalib/org/kde/qt -lqtjavaiface

(The library names "libqtjavaiface.so" and "libkdejavaiface.so" are the same 
ones Thomas Kuhn used with his kdebindings patches, which Richard Dale 
emailed along to me.)

With these rules in place, build libqtjavaiface.so and libkdejavaiface.so.  
Copy them to your /usr/lib directory.  Now you can build the ScribbleWindow 
example from qtjava like this.

gcj ScribbleWindow.java -o scribble --main=ScribbleWindow -lqtjavaiface

And, at least on my machine, it works!

adam