[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