{"id":7,"date":"2005-08-31T20:22:36","date_gmt":"2005-09-01T00:22:36","guid":{"rendered":"http:\/\/46.19.32.152\/blog\/?p=7"},"modified":"2015-10-26T20:36:36","modified_gmt":"2015-10-27T00:36:36","slug":"awt-native-interface-java-gcjhead-compat-big-merge","status":"publish","type":"post","link":"https:\/\/www.fitzsim.org\/blog\/?p=7","title":{"rendered":"libjawt.so, java-gcjHEAD-compat, Big Merge"},"content":{"rendered":"<p>\nHere&#8217;s a screenshot of a JOGL demo running on Sun and libgcj:\n<\/p>\n<p><a href=\"https:\/\/www.fitzsim.org\/screenshots\/jogl-demo-2005-08-31.png\"><img decoding=\"async\" src=\"https:\/\/www.fitzsim.org\/screenshots\/jogl-demo-2005-08-31-thumbnail.png\" alt=\"JOGL Demo on Sun and libgcj\"\/><\/a><\/p>\n<p>\nAs you can see, it&#8217;s hard to tell which is which!\n<\/p>\n<p><strong>Big Merge<\/strong><\/p>\n<p>The screenshot represents several efforts coming together.  First, the demo is running on natively-compiled GNU Classpath HEAD.  <a href=\"http:\/\/www.peakpeak.com\/~tromey\/blog\">Tom Tromey<\/a> recently finished the Big Merge, making Classpath a sub-directory of gcc\/libjava.  To develop this demo, I replaced gcc\/libjava\/classpath with a checkout of Classpath HEAD and rebuilt libgcj.  After patching a few places where divergences crept in I have a GCJ HEAD + Classpath HEAD development environment setup.  Developing in this way is much more pleasant than the previous merge-every-patch approach; now I use the same source checkout for libgcj and JamVM+Classpath.<\/p>\n<p><strong>java-gcjHEAD-compat<\/strong><\/p>\n<p>The screenshot shows me running the java command in the exact same way in both windows, thanks to <a href=\"http:\/\/www.fedoraproject.org\/wiki\/java-gcjHEAD-compat\">java-gcjHEAD-compat<\/a>.  It is an RPM spec file that allows you to create a first-class JPackage-style JVM alternative that points to a GCJ installation in a non-standard prefix.  For example, I&#8217;ve installed GCJ HEAD in \/home\/fitzsim\/install.  java-gcjHEAD-compat points \/usr\/bin\/java (through alternatives) to \/home\/fitzsim\/install\/bin\/gij.<\/p>\n<p>This is very convenient for developing libgcj as a JPackage JVM replacement since all JPackages assume the JVM is installed in \/usr\/lib\/jvm.  It&#8217;s also useful for building RPMs against libgcj HEAD, which I&#8217;ve done with JOGL in the screenshot.  Now, JOGL is a heavy user of the AWT Native Interface which is implemented by a small library, libjawt.so.  That brings me to my next topic.<\/p>\n<p><strong>libjawt.so Binary Compatibility<\/strong><\/p>\n<p>It has proved quite challenging to create a drop-in replacement for Sun&#8217;s libjawt.so.  The jawt.h and jawt_md.h headers that Sun includes in the <a href=\"http:\/\/java.sun.com\/j2se\/1.5.0\/docs\/guide\/awt\/1.3\/AWT_Native_Interface.html\">AWT Native Interface document<\/a> are marked confidential and proprietary so I didn&#8217;t want to refer to them when creating an implementation for GNU Classpath.  My initial libjawt.so attempt was not binary-compatible and so created problems for packages like JOGL that need to run on either libgcj or a proprietary JVM.<\/p>\n<p>Using gdb and ptype I was able to determine the layout of JAWT types, so now libgcj&#8217;s libgcjawt.so is binary-compatible, except that its SONAME is versioned by libtool.  But the SONAME of Sun&#8217;s libjawt.so is unversioned, simply &#8220;libjawt.so&#8221;, so even naming our library the same would not produce a binary-compatible result (e.g. &#8220;libjawt.so.6&#8221;) &#8212; and besides, doing so would cause confusion since libgcj&#8217;s &#8220;libjawt&#8221; is always present in the default library path, whereas Sun&#8217;s libjawt is not.  So, what to do?<\/p>\n<p>The last step in drop-in replaceability turned out to be a clever trick that Jakub Jelinek suggested:<\/p>\n<pre>\r\nlibjawt.so:\r\n\techo | $(GCJ_BIN_DIR)\/gcc$(gcc_suffix) -shared -O2 -fpic -o libjawt.so -Wl,-soname,libjawt.so -xc - -lgcjawt\r\n<\/pre>\n<p>That&#8217;s a line from java-gcj-compat&#8217;s Makefile.am.  It creates an empty library with the proper SONAME that links to the versioned libgcjawt.so.  That&#8217;s it!  java-gcj-compat&#8217;s libjawt.so gets installed in $JAVA_HOME\/jre\/lib\/i386 just like Sun&#8217;s and apps needing libjawt.so to build or run don&#8217;t know the difference!  I was relieved that this step was so simple &#8212; I was expecting linker script madness.<\/p>\n<p>The proof that this all works is in the screenshot; I built <a href=\"http:\/\/www.spindazzle.org\/green\">Anthony Green<\/a>&#8216;s <a href=\"http:\/\/people.redhat.com\/green\/FC4\/\">JOGL RPMs<\/a> using java-gcjHEAD-compat and its libjawt.so and I&#8217;m running the JOGL demo on both Sun and java-gcjHEAD-compat.  lsof shows the correct libjawt.so being loaded in each case:<\/p>\n<pre>\r\n$ \/usr\/sbin\/lsof | grep libjawt.so\r\njava      32435 fitzsim  mem       REG        3,2     2680     470785 \/usr\/lib\/jvm\/java-1.4.2-gcjHEAD-1.4.2.0\/jre\/lib\/i386\/libjawt.so\r\njava      32460 fitzsim  mem       REG        3,2     3824     812009 \/usr\/java\/jdk1.5.0_01\/jre\/lib\/i386\/libjawt.so\r\n<\/pre>\n<p>Now I want to see JOGL submitted to Fedora Extras and all this binary-compatibility work land in Fedora Core 5!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here&#8217;s a screenshot of a JOGL demo running on Sun and libgcj: As you can see, it&#8217;s hard to tell which is which! Big Merge The screenshot represents several efforts coming together. First, the demo is running on natively-compiled GNU Classpath HEAD. Tom Tromey recently finished the Big Merge, making Classpath a sub-directory of gcc\/libjava. &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.fitzsim.org\/blog\/?p=7\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;libjawt.so, java-gcjHEAD-compat, Big Merge&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-7","post","type-post","status-publish","format-standard","hentry","category-uncategorized","entry"],"_links":{"self":[{"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7"}],"version-history":[{"count":3,"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7\/revisions"}],"predecessor-version":[{"id":301,"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7\/revisions\/301"}],"wp:attachment":[{"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}