[Kde-java] GCJ and qtjava/kdejava

Richard Dale kde-java@kde.org
Fri, 8 Mar 2002 01:50:29 +0000


On Wednesday 06 March 2002 8:38 pm, Adam Dingle wrote:
> 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.
This is really good news if the source doesn't need any changes to build with 
gcj.

> - 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.
The bindings have JNI local leaks - I fixed quite a few leaks in the Qt 3 HEAD 
branch - so there may be excessive local references at the top level in 
QApplication.exec().
 
> 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 is the crash I got when I tried gcc 3.0.3 - I've already sent it to Adam, 
but here it is again for completeness. The gcj code threw an exception on 
returning from the first JNI function called:

tipitina duke 1491% HelloWorld
 In registerJVM..
 Exception in thread "main" java.lang.ExceptionInInitializerError: 
java.lang.NullPointerException
    at 0x0f81dab0: _Jv_ThrowSignal (/usr/local/lib/libgcj.so.2)
    at 0x0f81dae8: _Jv_equalUtf8Consts(_Jv_Utf8Const, _Jv_Utf8Const) 
(/usr/local/lib/libgcj.so.2)
    at 0x7ffff258: _r_debug (/lib/ld.so.1)
    at 0x0f8204c8: _Jv_JNI_Init() (/usr/local/lib/libgcj.so.2)
    at 0x0f82056c: _Jv_JNI_PopSystemFrame (/usr/local/lib/libgcj.so.2)
    at 0x0fe91b44: org.kde.qt.qtjava.registerJVM() 
(/export/src/gcjbindings/qtjava/javalib/org/kde/qt/libqtjavaiface.so)
    at 0x0fe93ac0: org.kde.qt.qtjava.__U3c_clinit__U3e_() 
(/export/src/gcjbindings/qtjava/javalib/org/kde/qt/libqtjavaiface.so)
    at 0x0f83b68c: java.lang.Class.initializeClass() 
(/usr/local/lib/libgcj.so.2)
 ...

But perhaps this only happens on PowerPC, and not Intel.

> 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.)
It would be nice to add some sort of option to configure in kdebindings - eg 
'--enable-gjc', which would build the extra libs. It's much easier now that 
Thomas's CNI callbacks aren't needed.

> 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!
I'm very envious! This is the best news about gcj since Thomas got it working 
in the first place. I must try gcc 3.0.4 on PowerPC, and hope it works better 
than 3.0.1 or 3.0.3 that I've tried.

-- Richard