Compiling Java with GCJ

Although Java isn't a popular choice for free projects, GJC can make it a viable option.
Compiling a Java Program with GCJ

Using GCC to run a Java program is familiar to anyone who has used it for C or C++ programs. To compile the Java program MyJavaProg.java, type:

gcj -c -g -O MyJavaProg.java

To link it, use the command:

gcj --main=MyJavaProg -o MyJavaProg MyJavaProg.o
This is just like compiling a C++ program mycxxprog.cc:
g++ -c -g -O mycxxprog.cc
and then linking to create an executable mycxxprog:
g++ -o mycxxprog mycxxprog.o
The only new aspect is the option --main=MyJavaProg. This is needed because it is common to write Java classes containing a main method that can be used for testing or small utilities. Thus, if you link a bunch of Java-compiled classes together, there may be many main methods, and you need to tell the linker which one should be called when the application starts.

You also have the option of compiling a set of Java classes into a shared library (.so file). In fact, the GCJ runtime system is compiled to a .so file. While the details of this belong in another article, if you are curious you can look at the Makefiles of Kawa (discussed below) to see how this works.

Features and Limitations of GCJ

GCJ is not only a compiler. It is intended to be a complete Java environment with features similar to Sun's JDK. If you specify the -C option to gcj it will compile to standard .class files. Specifically, the goal is that gcj -C should be a plugin replacement for Sun's javac command.

GCJ comes with a bytecode interpreter (contributed by Kresten Krab Thorup) and has a fully functional ClassLoader. The standalone gij program works as a plugin replacement for Sun's java command.

GCJ works with libgcj, which is included in GCC 3.0. This runtime library includes the core runtime support, Hans Boehm's well-regarded conservative garbage collector, the bytecode interpreter and a large library of classes. For legal and technical reasons, GCJ cannot ship Sun's class library, so it has its own. The GNU Classpath Project now uses the same license and FSF copyright that libgcj and libstdc++ use, and classes are being merged between the two projects. We use the GPL but with the special exception that if you link libgcj with other files to produce an executable, this does not by itself cause the executable to be compiled by the GPL. Thus, even proprietary programs can be linked with the standard C++ or Java; runtime libraries.

The libgcj library includes most of the standard Java classes needed to run non-GUI applications, including all or most of the classes in the java.lang, java.io, java.util, java.net, java.security, java.sql and java.math packages. The major missing components are classes for doing graphics using AWT or Swing. Most of the higher-level AWT classes are implemented, but the lower-level peer classes are not complete enough to be useful. Volunteers are needed to help out.

Interoperating with C/C++

Although you can do a lot using Java, sometimes you want to call libraries written in another language. This could be because you need to access low-level code that cannot be written to Java, an existing library provides functionality that you need and don't want to rewrite, or you need to do low-level performance hacks for speed. You can do all of these by declaring some Java methods to be native and, instead of writing a method body, provide an implementation in some other language. In 1997, Sun released the Java Native Interface (JNI), which is a standard for writing native methods in either C or C++. The main goal of JNI is portability in the sense that native methods written for one Java implementation should work with another Java implementation, without recompiling. This was designed for a closed-source, distributed-binaries world and is less valuable in a free-software context, especially because you do have to recompile if you change chips or the OS type.

To ensure JNI's portability, everything is done indirectly using a table of functions. This makes JNI very slow. Even worse, writing all these functions and following all the rules is tedious and error-prone. Although GCJ does support JNI, it also provides an alternative. The Compiled Native Interface (CNI, which could also stand for Cygnus Native Interface) is based on the idea that Java is basically a subset of C++ and that GCC uses the same calling convention for C++ and Java. So, what could be more natural than being able to write Java methods using C++ and using standard C++ syntax for access to Java fields and calls to Java methods? Because they use the same calling conventions and data layout, no conversion or magic glue is needed between C++ and Java.

Examples of CNI and JNI will have to wait for a future article. The GCJ manual (gcc.gnu.org/onlinedocs/gcj) covers CNI fairly well, and the libgcj sources include many examples.

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Re: Compiling Java with GCJ

Federiko's picture

Thank you for this information. I have a Java homework on this problem. I think that I can solve it now.

Compile issues, MinGW

Confused eddie's picture

Hi, I am new to java and MinGW (GCC), I am running win 7 (64 bit) and minGW 3.4.5 (Vista special r3) and from what I can see I'm using gcj 3.4.5. and crimson editor (Although ) I have a few questions :

1) I have tried compiling the file test.java with the following contents

public class test
{
public static void main(String args[])
{
System.out.println("This is a test.");
}
}
<\code>

If I try compile with "C:\MinGW\bin\gcj.exe" test.java -o test.exe I get the following 3 error messages :

C:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../libgcj.a(win32.o):win32.cc:(.data+0x0):...
multiple definition of `_CRT_MT'
C:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../libmingw32.a(crtst.o):crtst.c:(.bss+0x0):...
first defined here
C:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../libmingw32.a(main.o):main.c:(.text+0xd2):...
undefined reference to `WinMain@16'
collect2: ld returned 1 exit status
<\code>

If I run "C:\MinGW\bin\gcj.exe" -c -g -O test.java and then "C:\MinGW\bin\gcj.exe" --main=test -o test test.o the third error message disspears. I'm afraid I don't understand what the difference is between the two compile methods and was hoping you could elaborate. Would I be correct in saying the second method tries to compile then link the various files ? (I've mostly worked in Matlab and a little octave, so for now the java jargon is eluding me a bit.)

2) The first error "_CRT_MT" seems to be a very uncommon error or atleast I'm having trouble trying to find a fix for it. Does any one know where it originates or why ? And if there is some easy fix for it ? From what I've read it comes from defining _CRT_MT in more then one place. I saw a post saying one must include the line "_CRT_MT=1" in your code but it doesn't say where, I tried inserting it in various places and had no improvements.

3) Would any of these things have to do with my version of windows/MinGW ?

Thanks

pass parameters to the .exe file?

Anonymous's picture

Hi,

is it possible to pass parameters to an executable file? Or do I need to pass it somehow when I compile the Java code into the exe file using gcj? If so, how do I do that?
I need something replacing this sort of command-line:
java app 12 4 25 56 file.out

Thank you. :)

Hi, I'm new in MinGW and I

Anonymous's picture

Hi,
I'm new in MinGW and I try to compile my first program :

public class FirstApp
{ 
	public static void main(String args[])
        {
    		System.out.println("This is a test.");
  	}
}

First I type:

gcj -c -g -O FirstApp.java

An object file is then created.

Then I type

gcj --main=FirstApp -o FirstApp FirstApp.o

An exe file is then created.

Finally, when I type

FirstApp.exe 

or

FirstApp

, nothing happens...
In other words: "This is a test" isn't displayed.

Can you tell me why ?

My config:
Windows Xp Pro Pack 3
MinGW 5.1.6
libiconv added to the MinGW directory

Thank you!

Compiling Java applications to native code

Anonymous's picture

I could suggest a GCJ alternative - JCGO (developed by IvMaiSoft LLC) which is a Java source to C translator. The tool translates all the classes of your java program at once and produces C files (one .c and .h for each class), which could, further, be compiled (by third-party tools like GCC or VC++) into highly-optimized native code for the target platform (eg., for Windows, Linux, Solaris or embedded).
The produced native code is quite compact unless you are translating a GUI application (you can see a number of sample applications of the JCGO demo page; HelloWorld executable size is only 12 KiB (UPX'ed)). Also, JCGO automatically identifies some immutable static Java objects (like strings) and they go into read-only data program section (an application on an embedded platform with its code in ROM might benefit from this feature). Memory management is performed by BoehmGC (like GNU GCJ does).

That is what I call shameless

Anonymous's picture

That is what I call shameless advertising.

Excellent...

Jerry McBride's picture

Thank you for the mini tutorial. It's been most illuminating. I'm now running all of my java apps "natively"! Couldn't have done it without this!!

Jerry

---- Jerry McBride

file search

Anonymous's picture

File search at royalsearcher.com

Excuse for the stupid

Anonymous's picture

Excuse for the stupid question, please!

Can you tell me how to compile an operating system with gcj?

This page saves my life! Very

Anonymous's picture

This page saves my life! Very nice page!

Dynamic loading

Mehdi's picture

GCJ is great, I just need to understand how to achieve "post deployment" dynamic loading.
I mean, doing something like plugins for the eclipse IDE. You can add plugins (mainly jar files) to the eclipse IDE that is already deployed! As long as the plugin implements some Interface, it can be dynamically loaded by eclipse IDE and the functionality provided by that plugin is available to Eclipse users. This is just classic Java.
As far as I can understand, it is perfectly possible to do that with GCJ. However I had a problem.

I tried to use Class.forName("myC"); which worked fine. However the program doesn't see all classes, but only the ones that where there when the main was compiled. If I add some more classes in the right folder that implement the right interface, and re-run the program it doesn't accept those new class files at all (I raise an exception when the object cannot be created).

Has anyone succeeded in making EXE produced by GCJ accept some new classes/jars (either .class, or preferably in some dll,...) after the EXE was deployed.
Anything I should be aware of? any special flag??

Thanks in advance

I able to compiled my java ap

Anonymous's picture

I able to compiled my java app with gcj, but unable to run it properly. The app required 4 arguments two of which are required for FileInputStream and FileOutputStream, also has several imports

import javax.crypto.*;
import javax.crypto.spec.*;

if I run with Java command " java MyApp mode inputstream output text", the app run perfectly, but when i ran after compile with GCJ
"MyApp.exe mode inputstream output text" its does not work. It does not produced same result as java commandline. Any ideas?

Thankx

I have just the same

Anonymous's picture

I have just the same problem, with FileOutputStream.

ld.exe cannot find -lgdi32

Anonymous's picture

Set your PATH with 'start\control panel\System'
Select the Advanced tab, Environment Variables;
Add the System variable GCJ= c:\gcc-4.0
Add the System variable GCJ_BIN= %GCJ%\bin;%GCJ%\i686-pc-mingw32\bin ;%GCJ%\i686-pc-mingw32\ming32\bin;%GCJ%\libexec\gcc\i686-pc-mingw32\4.0.0;

Select the System variable Path and edit it.
Add %GCJ_DIR%;
to the variable.

Restart eclipse.

get a error with GCJ

Anonymous's picture

gcj --main=HelloWorld -o HelloWorld.exe obj\HelloWorld.o -Lf:\swt

(this instruction get automatic this)
f:\gcj\thisiscool-gcc\gcc-4.0\bin\..\lib\gcc\i686-pc-mingw32\4.0.0\..\..\..\..\i
686-pc-mingw32\bin\ld.exe: cannot find -lgdi32
and the exe is not there

re: get a error with GCJ

Anonymous's picture

The problem seems to be the bundle that you are using for gcj, (ie www.thisiscool.com) Version 4.0.0 is missing elements from the runtime - Download the w32api-3.2 from http://www.mingw.org/download.shtml will resolve this problem.

Nik

get a error with GCJ

Anonymous's picture

Install the "Microsoft Platform SDK" and make sure that the /lib directory from the SDK is in your library path.

I get the same error too. :(

Anonymous's picture

I get the same error too. :(

Re: Piece of Crap

Anonymous's picture

GCJ is a piece of crap!!!

hahahaha what a useless

Anonymous's picture

hahahaha what a useless comment.

(not that this is any better)

More information

Nihilist's picture

I ran into a few problems while trying to make this work. First of all, I'm using MingW's gcj, not Cygwin. (Cuz I don't like carrying cygwin1.dll around with me.) MingW doesn't come with an iconv implementation, so you have to download the 'binaries' and 'developer files' from here: http://gnuwin32.sourceforge.net/packages/libiconv.htm.

Second problem was the fact that I created my first app with a package. The article doesn't tell you what happens when you do that. Let me try to explain.

You create a Java source file, called Main.java, with the package test.foo. A sample:
package test.foo;

public class Main {
public static void main(String[] args) {
System.out.println("The world says hi!");
}
}

Using GCJ, you turn it into an object using:
gcj -c -g -O Main.java
This step will work without a problem.

However, when you go to turn the object into an executable, the problems will begin. If you try to use the following command:
gcj --main=Main -o Test Main.o
It'll chuck some obnoxious error.

Turns out that you have to tell it the package for the main class:
gcj --main=test.foo.Main -o Test Main.o

Should work fine now.

Where to put JDBC jar file when connecting to MySQL

lofloa's picture

Hi,

I am trying to use the JDBC connector for MySQL. The java program compiles and links ok with gcj but when I run it is not seeing the jar file where all the classes for the connection are defined.

Where should I put this file?

In the 'standard' java environment I put them in the jre/lib/ext folder.

What's the equivalent under gcj?

Thanks,

Francisco

Is there an official comparison with JDK 5.0 or 1.4.2?

Anonymous's picture

There are official comparisons with 1.4.2 when it comes to GNU Classpath. But none for GCJ. Is there a way to make that available? Also, why aren't GNU Classpath APIs distributed as native code using GCJ?

V
Java Technologies

MinGW GCJ

Aanand's picture

I am using MinGW 3.2. And I tried to compile my java program to native executable.

This is the command i issued. But it said "cannot find -l iconv ". What should i do to compile the program correctly.

$ gcj -g -O MyNewClass.java
d:\MinGW\bin\..\lib\gcc\mingw32\3.4.2\..\..\..\..\mingw32\bin\ld.exe: cannot find -liconv
collect2: ld returned 1 exit status

Thanks in advance.

try: 1. download from http:/

Anonymous's picture

try:
1. download from http://gnuwin32.sourceforge.net/packages/libiconv.htm
"Binaries" AND "Developer files"
2. install "Binaries" to directory where is mingw installed (not to proposed GnuWin32 directory), so finally /bin from "Binaries" matches /bin from mingw, /lib to /lib, etc...
3. unpack "Developer files" to mingw directory, /lib to /lib from mingw ..., as above
seems to work...

It's Worked... thank you

jishin's picture

It's Worked... thank you

Re: Compiling Java with GCJ

Anonymous's picture

I can't find out how to get this gcj stuff!

gcj is a free compiler

Raj Kumar Sanpui's picture

gcj is a free compiler available with almost all flavours of linux.
It comes with gcc (GNU collection of compilers).

gcj is a free compiler

Raj Kumar Sanpui's picture

gcj is a free compiler available with almost all flavours of linux.
It comes with gcc (GNU collection of compilers).

gcj is a free compiler

Raj Kumar Sanpui's picture

gcj is a free compiler available with almost all flavours of linux.
It comes with gcc (GNU collection of compilers).

Re: Compiling Java with GCJ

Anonymous's picture

My application needs to set the memory usage. I use
java -jar -Xms256m -Xmx384m myapplication.jar

Is there any way to set these parameters when I compile my application using GCJ?

Re: Compiling Java with GCJ

Anonymous's picture

Can we expect the AWT toolkit for windows will be implemented in future releases?

Re: Compiling Java with GCJ

Anonymous's picture

AWT isn't supported yet but SWT works with GCJ, and I like it MUCH better than AWT or even Swing.

Here's the how-to:
http://www-106.ibm.com/developerworks/java/library/j-nativegui2/

Go to eclipse.org to get SWT.

Re: Compiling Java with GCJ

Anonymous's picture

The real trick is not compiling with gcj, but getting the compiled application to run. I have yet to find documention indicating what classpaths should be used to avoid errors like this:

java.awt.AWTError: Cannot load AWT toolkit: gnu.awt.gtk.GtkToolkit not found in [file:./, core:/]
>
java.awt.AWTError: Cannot load AWT toolkit: gnu.awt.gtk.GtkToolkit not found in [file:./, core:/]
>

Re: Compiling Java with GCJ

Anonymous's picture

Graphical applications are not yet supported. AWT/Swing does not work. Sorry...

--Nathan Chilton

Re: Compiling Java with GCJ

Anonymous's picture

From I've been able to gather so far, is graphical applications are indeed supported. Many applets work out out of the box. But only on some platforms. It seems in the official versions, cygwin is disabled from building libjava all together. Only hacked versions are able to build libjava, and those do not seem to support the graphical components.

However, my search is not complete. Maybe somewhere there is a version gcj source which will build completely for cygwin.

Bill

Re: Compiling Java with GCJ

Anonymous's picture

It looks to me like all the swing components are present and compiles Ok why is it not available and what is stopping it? I have a project I would very much like to use this on and I don't understand if all is present why it is not available. Please explain. This is the very same message I get from the Kaffe VM.

Re: Compiling Java with GCJ

Anonymous's picture

The real trick is not compiling with gcj, but getting the compiled application to run. I have yet to find documention indicating what classpaths should be used to avoid errors like this:

java.awt.AWTError: Cannot load AWT toolkit: gnu.awt.gtk.GtkToolkit not found in [file:./, core:/]
>
java.awt.AWTError: Cannot load AWT toolkit: gnu.awt.gtk.GtkToolkit not found in [file:./, girlscore:/]
>

Re: Compiling Java with GCJ

Anonymous's picture

Hi, I'm interested in this utility. But...there seems to be much to do with the libgcj, which provide the gcj version of java libraries.

See, I've used both method String.replaceAll and the java.util.regex package in my project, but found neither is supported by gcj now. I'm using gcj version 3.3.1 under cygwin, on Windows 2000. Though the simplest HelloWorld works well, my real project failed. That's sad news for me.

Are there any available supports for both of these features?

Re: Compiling Java with GCJ

Anonymous's picture

I've tried gcj on a test program and it compiled and ran beautifully ... as long as I ran it with C:cygwinin in my path. Otherwise it couldn't find required dll's ('cywin1.dll', etc).

It doesn't look as though I can give the .exe to someone else and expect them to be able to run it unless they have cygwin installed and in their path - which defeats my purpose.

Is there a way around this?

Thanks, Nathan

Re: Compiling Java with GCJ

Anonymous's picture

yes, there is a way around this. Include -mno-cygwin option when you compile.
Example:

gcj --main=Hello -mno-cygwin -o Hello Hello.java

The main option tells which class file is to be used as the starting file, just in case there are more than one class files that have their own main.

hope this helps.

Re: Compiling Java with GCJ

Anonymous's picture

You just have to give them the compiled executable plus the cygwin dlls...

Re: Compiling Java with GCJ

Anonymous's picture

just with a -mno-cygwin solves everything

Re: Compiling Java with GCJ

Anonymous's picture

Use the MINGW-version of GCJ, which doesn't require cygwin1.dll. Works very well and can be used in commercial projects. Creates one single self-contained win32-executable.

-- Mattiasw

I can't compile using the GCJ distribution

Ivan R. Ch's picture

I've trying to compile just the hello world, and when I try to link, get this error:
gcj --main=HelloWorld -o HelloWorld.exe obj\HelloWorld.o -Lf:\swt
:\gcj\thisiscool-gcc\gcc-4.0\bin\..\lib\gcc\i686-pc-mingw32\4.0.0\..\..\..\..\i
86-pc-mingw32\bin\ld.exe: cannot find -lgdi32

I dont know why, what I need to make the exe ?

Re: Compiling Java with GCJ

Anonymous's picture

How about compiling statically? You just get a huge binary

Re: Compiling Java with GCJ

Anonymous's picture

Some questions:

* how well does getClass() work?
ie given an object, o, is this supported?
Class c = o.getClass();

* is instanceof supported?
if (o instanceof MyWidget) {...}

* how well does gcj handle run-time class loading?
eg Class c = Class.forName("com.acme.Widget");

* how well does gcj handle run-time reflection?
eg can code query the methods available on class C?
can they be dynamically invoked?

* are multiple class-loaders supported?
eg: if a class has a static member, and it is explicitly loaded
via two different class-loaders, are there two separate
instances of the static member variable? (there should be).

* is dynamic class generation supported?
Java 1.4 provides "dynamic adapters" as an alternative
to using inner classes as adapters. I believe these
generate (simple) new classes on the fly.

Thanks,

Simon

Re: Compiling Java with GCJ

Anonymous's picture

* how well does getClass() work?
ie given an object, o, is this supported?
Class c = o.getClass();

It works just fine.

* is instanceof supported?
if (o instanceof MyWidget) {...}

Of course. I doubt any non-trivial Java apps would work if this wasn't the case!

* how well does gcj handle run-time class loading?
eg Class c = Class.forName("com.acme.Widget");

Very well. Your class can be in a shared library, which will be automatically loaded by Class.forName(). Alternatively, you can even mix bytecode (.class files) with native compiled Java.

* how well does gcj handle run-time reflection?
eg can code query the methods available on class C?
can they be dynamically invoked?

Reflection and Invocation are fully supported.

* are multiple class-loaders supported?
eg: if a class has a static member, and it is explicitly loaded
via two different class-loaders, are there two separate
instances of the static member variable? (there should be).

Currently there may be bugs in this area, however they are being worked on. There is no fundamental reason why this shouldn't work.

* is dynamic class generation supported?
Java 1.4 provides "dynamic adapters" as an alternative
to using inner classes as adapters. I believe these
generate (simple) new classes on the fly.

Yes, dynamic proxies are supported.

Re: Compiling Java with GCJ

Anonymous's picture

Hi all-,
Am I the only one largely unimpressed by GCJ?
Most of the assumptions (like "not many OS projects") in the
begining of the article are hard to comprehend.
Start up time will improve when the JVM becomes part of the OS (like in Mac OS X) . This will happen in JDK1.5 and there is
no need for compilation to native code.
Speaking of which, how do you plan to transport classes over (let's) RMI in a JINI environment, between different CPUs?

C'mon ... no serious developer should by this! Get real.

Re: Compiling Java with GCJ

Anonymous's picture

I would love to know what OS you are using on your Mac that gives you a built in JVM. My MacOS X 10.3 (Panther) just has the JVM as an application level component, just like other platforms supported by Java. For applets, I actually find the fastest starting JVM that I use regularly is the Microsoft Virtual Machine, but only if I optimize the code to with a few tricks I have learned along the way. However, in most cases it is the time it takes to load and initialize the classes into an applet that is noticable, not the actual time it takes to load the JVM into memory.

On most platforms, Java is just in time compiled. My experience has been this speeds Java by about a factor of 2 to a factor of 6 depending on the application. On platforms where Java is not JIT compiled, such as J2ME or RedHat 7.1 you'll really notice the slowdown.

In theory, J2EE features can be implimented in the same way they are in a JVM. I do not really see a significant difference between "ahead of time compiling" as in "gcj" and "just in time compiling". It would be fairly trivial to compile a class as a shared object for dynamic loading at runtime.

Bill

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix