libgcj is distributed under the GPL, with the 'libgcc exception'.
This means that linking with libgcj does not by itself cause
your program to fall under the GPL. See LIBGCJ_LICENSE in
the source tree for more details.

libgcj has a bytecode interpreter that allows you to mix .class files with
compiled code. It works pretty transparently: if a compiled version of a class is
not found in the application binary or linked shared libraries, the class loader
will search for a bytecode version in your classpath, much like a VM would. Be
sure to build libgcj with the --enable-interpreter option to enable this
functionality.

The program "gij" provides a front end to the interpreter that behaves
much like a traditional virtual machine. You can even use "gij" to run a shared library
which is compiled from java code and contains a main method:

$ gcj -shared -o lib-HelloWorld.so HelloWorld.java
$ gij HelloWorld

This works because gij uses Class.forName, which knows how to load shared objects.

Just look in the 'libjava' directory of libgcj and see what classes
are there. Most GUI stuff isn't there yet, that's true, but many of
the other classes are easy to add if they don't yet exist.

I think it's important to stress that there is a big difference
between Java and the many libraries which Java supports. Unfortunately,
Sun's promise of "write once, run everywhere" assumes much
more than a JVM: you also need the full set of JDK libraries. Considering
that new Java APIs come out every week, it's going to be impossible
to track everything.

To make things worse, you can't simply run Sun's JDK classes on
any old JVM -- they assume that a bunch of native methods are also
defined. Since this native method requirement isn't defined by the
JDK specs, you're effectively constrained to using Sun's JVMs if you
want to use Sun's JDK libraries. Oh yes -- you could also reimplement
all of those native methods yourself, and make sure they behave exactly
as Sun's do. Note that they're undocumented!

Yes. libgcj now has experimental support for JNI, in addition to
its native Compiled Native Interface (CNI). gcjh will generate JNI
stubs and headers using the "-jni" option. However, we do
prefer CNI: it is more efficient, easier to write, and (at least
potentially) easier to debug.

We use CNI because we think it is a better solution, especially
for a Java implementation that is based on the idea that Java is
just another programming language that can be implemented using
standard compilation techniques. Given that, and the idea that languages
implemented using Gcc should be compatible where it makes sense,
it follows that the Java calling convention should be as similar
as practical to that used for other languages, especially C++, since
we can think of Java as a subset of C++. CNI is just a set of helper
functions and conventions built on the idea that C++ and Java have
the *same* calling convention and object layout; they are binary
compatible. (This is a simplification, but close enough.)

Certainly, provided the licenses are compatible.
However, in many cases, if you wanted to contribute the
code back into the official libgcj distribution, we would require that the
original author(s) assign copyright to the Free Software Foundation.

As of March 6, 2000, libgcj has been relicenced, and copyright has
been assigned to the FSF. This allows
us to share and merge much of the libgcj codebase with the
Classpath project.
Our eventual goal is for Classpath to be an upstream source provider for libgcj,
however it will be some time before this becomes reality: libgcj and Classpath
have different implementations of
many core java classes. In order to merge them, we need to select the
best (most efficient, cleanest) implementation of each method/class/package,
resolve any conflicts created by the merge, and test the final result.
Needless to say, this is a lot of work. If you can help out, please
let us know!

When using gcj to link a Java program, you must use the --main=
option to indicate the class that has the desired main method.
This is because every Java class can have a main method, thus
you have to tell gcj which one to use.

The reason is that when you compile to bytecode you lose a lot
of information about program structure etc. That information helps
in generating better code. We can in theory recover the information
we need by analysing the structure of the bytecodes, but it is sometimes
difficult - or sometimes it just that no-one has gotten around to
it.

Specific examples include loop structure (gcc generates better
code with explicit loops rather than with the equivalent spaghetti
code), array initializers, and the JDK 1.1 `CLASS.class' syntax,
all of which are represented using more low-level constructs in
bytecode.

GCJ looks for classes to compile based on the CLASSPATH environment
variable. libgcj.jar and other files are found relative to the
path of the compiler itself, so it is safe to move the entire compiler tree
to a different path, and there is no need to include libgcj.jar
in your CLASSPATH.

GCJ compiles only the files presented to it on the command line. However,
it also needs to scan other files in order to determine the layout of other
classes and check for errors in your code. For these dependencies, GCJ will
favour .class files if they are available because it is faster to parse a
class file than source code.

It could be any number of things. One common mistake is
having your CLASSPATH environment variable pointing
at a third party's java.lang and friends. Either unset
CLASSPATH, or make sure it does not refer to core
libraries other than those found in
libgcj.jar.Note that newwer versions of
GCJ will reject the core class library if it wasn't
generated
by GCJ itself.

This is "normal"; the Garbage Collector (GC) uses it to determine
stack boundaries. It is ordinarily caught and handled by the GC -- you
can see this in the debugger by using cont to continue to the
"real" segv.

If your programs allocate many small, short lived objects, the
heap could be filling and triggering GC too regularly. Try increasing
the initial and maximum heap sizes as per 5.5 How do I increase
the runtime's initial and maximum heap size?

RE - array accesses. We have sub-optimal runtime checking code,
and the compiler is still not so smart about automatically removing
array checks. If your code is ready, and it doesn't rely on them,
try compiling with --no-bounds-check.

Try static linking. On many platforms, dynamic (PIC) function
calls are more expensive than static ones. In particular, the
interaction with boehm-gc seems to incur extra overhead when shared
libraries are used.

If your Java application doesn't need threads, try building libgcj
using --enable-threads=none. Portions of the libgcj runtime are
still more efficient when single-threaded.

It is possible to turn on verbose GC output by suppressing the -DSILENT
flag during build. One way to do this is to comment out the line with
#define SILENT 1 from boehm-gc/configure before configuring libgcj.

The GC will print collection statistics to stdout. (Rebuilding boehm-gc
alone without this flag doesn't seem to work.)

Some programs that allocate many small, short-lived objects can cause
the default-sized heap to fill quickly and GC often. With the 2.95.1
release there is no means to adjust the heap at runtime. Recent snapshots
provide the -ms and -mx arguments to gij to specify the initial and
maximum heap sizes, respectively.

Currently, only single threaded Java code may be used by the profiler
(gprof). POSIX threads seem to be incompatible with the gmon stuff.

A couple of other tools that have been mentioned on the GCJ mailing list are
sprof and cprof. The former is part of GNU libc.

Programming Issues

6.1 Are there any examples of how to use CNI?

Glenn Chambers has created a couple
of trivial examples for
version 2.95
and version 3.0.
As a comparison, here
is the same example as a JNI application using
Kaffe. The same code will
work with GCJ, as shown here.

Note that for version 2.95, you must compile the C++ files
used for CNI with the -fno-rtti option.
This constraint does not apply in version 3.0 and later.

For questions related to the use of GCC,
please consult these web pages and the
GCC manuals. If that fails,
the gcc-help@gcc.gnu.org
mailing list might help.
Comments on these web pages and the development of GCC are welcome on our
developer list at gcc@gcc.gnu.org.
All of our lists
have public archives.

Copyright (C)
Free Software Foundation, Inc.
Verbatim copying and distribution of this entire article is
permitted in any medium, provided this notice is preserved.