Compiling Java 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.oThis is just like compiling a C++ program mycxxprog.cc:
g++ -c -g -O mycxxprog.ccand then linking to create an executable mycxxprog:
g++ -o mycxxprog mycxxprog.oThe 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.
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.
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.
Today’s modular x86 servers are compute-centric, designed as a least common denominator to support a wide range of IT workloads. Those generic, virtualized IT workloads have much different resource optimization requirements than hyperscale and cloud applications. They have resulted in a “one size fits all” enterprise IT architecture that is not optimized for a specific set of IT workloads, and especially not emerging hyperscale workloads, such as web applications, big data, and object storage. In this report, you will learn how shifting the focus from traditional compute-centric IT architectures to an innovative disaggregated fabric-based architecture can optimize and scale your data center.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
| Trying to Tame the Tablet | May 08, 2013 |
- Using Salt Stack and Vagrant for Drupal Development
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- New Products
- Validate an E-Mail Address with PHP, the Right Way
- Drupal Is a Framework: Why Everyone Needs to Understand This
- A Topic for Discussion - Open Source Feature-Richness?
- New Products
- New Products
- Home, My Backup Data Center
- Developer Poll
- This is the easiest tutorial
3 hours 24 min ago - Ahh, the Koolaid.
9 hours 2 min ago - git-annex assistant
15 hours 2 min ago - direct cable connection
15 hours 24 min ago - Agreed on AirDroid. With my
15 hours 35 min ago - I just learned this
15 hours 39 min ago - enterprise
16 hours 9 min ago - not living upto the mobile revolution
19 hours 33 sec ago - Deceptive Advertising and
19 hours 36 min ago - Let\'s declare that you have
19 hours 37 min ago
Enter to Win an Adafruit Prototyping Pi Plate Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Prototyping Pi Plate Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- Next winner announced on 5-21-13!
Free Webinar: Linux Backup and Recovery
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.




Comments
Re: Compiling Java with GCJ
I agree with the remarks about the beginning of the article. I would go further and criticize the claim that the two phase approach of Java is similar to C - it is much more similar to Basic with an initial compilation to a state that is later interpreted. Some may not like seeing Java compared to Basic or the original implementation of Pascal with p-code, but that is the Java model.
As a former OS internals developer, I wonder exactly what is supposed to be meant by "when the JVM becomes part of the OS" and how that is supposed to improve startup time to any great extent. It is the class load time and the byte code interpretation time that is the big issue here, not how long it takes to start the process running the JVM. Putting the JVM inside the kernel like a device driver would not be at all helpful in a virtual memory environment. Requiring a service trap from the application code to the kernel to get to the JVM would slow things down much more. If the claim is that putting the JVM on the same distribution CD as the OS will somehow speed things up, that does not make any sense. As for the JVM becoming part of the OS in JDK 1.5, I have not seen any announcement at www.java.sun.com about that. Besides, the JDK is irrelevant at runtime because the JRE is what interprets the byte codes in the class file.
As for transporting classes, a better example would be running Java classes inside a web browser for an applet. That is where the portability of Java classes is worth the cost at runtime to interpret everything or use a "not quite Just In Time" compiler that detects when too much time has been wasted and then optimizes code that may not run again.
In a servlet environment, noticing repeatedly executed code can have a payoff for future requests. For a Java application that runs for a while and then exits, the JIT optimizations are too late for any big payoff in performance.
Sun has resisted having Java be a compiled language all along. Whether this has helped them sell faster hardware is unknown but it certainly has slowed acceptance of Java in many cases. GCJ has the potential to be the perfect solution for cases where Java as source is desired but execution speed is important. This would allow source to be in a language that has many advantages, yet allow the installation to be specific to the hardware and OS for execution speed similar to C++.
Re: Compiling Java with GCJ
Java hasn't been "interpreted" for a long while now. It is compiled "just-in-time", which is a totally different thing. The code that runs is real machine code for the actual processor type it is running on, unlike "p-code" or similar.
I don't know what the comment "when the JVM becomes part of the OS" comment means either. However there is a feature in Java1.5 where starting a new java application will *not* start a new JVM intance. Instead, it just loads the classes associated with the new application into an existing JVM. And a JVM can be left "idle in the background" when no java apps at all are running, so that when one is started it starts much quicker.
So whether you are running 1, 2, 5 or 50 java-based apps, there is only one JVM. This is possible because using different class-loaders can totally isolate applications from each other; they aren't aware that they are sharing a JVM.
Possible issues that I can see, though, involve:
* process priority ("nice" etc)
* process killing (kill -9)
* JNI libraries loaded by one app crashing the JVM
In many cases, however, sharing a JVM could be beneficial, particularly if the java standard libraries only need to be loaded once (and JIT'ed once).
Yes, the app itself still needs to be "JIT'ed" when run.
Re: Compiling Java with GCJ
Most people don't need to use RMI in a JINI environment. They just want something that works, nicely, for writing apps. They want a rich programming environment with overflow detection, garbage collection, and a nice simple, usable object model. You are right that for a lot of things Java is currently used for, gcj probably won't work, but for a lot of things C and C++ are used for, gcj will work *better*.
Re: Compiling Java with GCJ
Your vision of the uses for Java is very limited. There are times that we want to reuse code for Windows client apps from other types of apps and we don't want to re-write to C++ or VB or something.
GCJ (and other native compilers) are useful in these cases because we want to protect our source code (not all software is free.. some of us need to eat). Platform portability is not needed and not even desirable.
The Java class format and obfuscators are not good at protecting source code well enough. Native compilers are much better.
Also telling a user to copy one file is much easier than telling him to install a JVM, set the classpath, etc..
GCJ + SWT is very attractive.
Re: Compiling Java with GCJ
Hallo ,
Can i import c++ code to java code using the cni interface and compile it to a class file (and how)??
Sbile
Re: Compiling Java with GCJ
"Although Java isn't a popular choice for free projects [...]"
Yeah, sure... Number of projects registered at Sourceforge, by technology:
C (10368)
C++ (9957)
Java (8101)
Perl (4413)
PHP (6103)
Re: Compiling Java with GCJ
Yea but how many of those have made it into a linux distrobution?
Re: Compiling Java with GCJ
After reading this, I decided to do some rudimentary benchmarking. Here are my results and comments:
CPU OS Compiler JVM Parsing Unparse
500Cel W2K Javac 1.4.1_01 JSE 1.4.1_01 1.8 (2.25) 1.6 (2) (interpolation to 400Mhz)
400Cel RH8 Javac 1.4.1_01 JSE 1.4.1_01 2.5 2.3
400Cel RH8 Jikes JSE 1.4.1_01 2.5 2.3
400Cel RH8 IBM-1.4.0 IBM-1.4.0 5.3 2.3
400Cel RH8 gcj Native Code 6.8 4.3
400Cel RH8 Javac 1.4.1_01 J2ME/Personal 46.9 11.0
400Cel RH8 Javac 1.4.1_01 gnu (gij) 142 6.7
400Cel RH8 Jikes Wonka 170 347
Notes: All tests were repeated for 10,000 iterations. This is the average per iteration in milliseconds. The
tested routine is an xml parser which is processor intensive. There is very little network/disk
utilization. Most of the the other JVM projects seem dead. I could not test the WebLogic
Jrockit JVM as that requires (?) Redhat Advanced Server. Sun seems to be doing some
thing right as their JVM seems to smoke all the others...
Re: Compiling Java with GCJ
Strange, testing numerical array operation (say dot product of two double array of length 1000, repeated 4 x 1000000 times) gcj is almost as fast as gcc (10sec vs 17 sec) when Sun jdk1.4 is 2.5 to 3 times slower (55 sec) .
This is great stuff for me. Developping in java, with all its comfort, and then compile it to be as fast as gcc.
Re: Compiling Java with GCJ
To correct my numbers in the previous message:
gcj (-O3, no bounds check) : 20 seconds, gcc (-O3) : 17 seconds, JDK HotSpot 1.4.1_01: 55 seconds. Al this very approximate, but seeing the difference no neeed of statistical test.
Re: Compiling Java with GCJ
Did you test with the server version of hotspot jvm?
java -server
Default is client.
Re: Compiling Java with GCJ
The IBM 1.3.1 JVM smokes the IBM 1.4.0 JVM (and all of the Sun JVMs, last I heard). For some reason, the IBM JVM has gotten slower in the latest revision. Also, what optimizations did you use with gcj. -O2 at the minimum. You should also consider -O3, -fno-bounds-checking and -fomit-frame-pointer.
On the other hand, I'm currently working with some acoustic modeling code that someone else translated from Fortan to Java. The gcj dynamically linked binary takes 10 times as long to run as the Sun 1.4.1_01 JVM, and statically linking the binary makes it take 20 times longer than the JVM. The source code is identical. I don't know what's wrong. It may be that StrictMath is too young in gcj. StrictMath isn't available in GCJ 3.0 (the default version under Debian Linux), but is available in GCJ 3.2.
When can we expect suport for Swing?
I would be really really impressed of you could compile Swing apps.
Re: When can we expect suport for Swing?
Actually some swing applications compile. The main limitations seems to be missing methods. For example, to get one of my applications to compile I had to change code from:
JEditorPane pane=new JEditorPane(url);
pan.setEditable(false);
to:
JEditorPane pane=new JEditorPane(url);
final Class [] params = { Boolean.TYPE };
final Object [] args = { Boolean.FALSE };
try {
JeditorPane.class.getMethod(
"setEditable",params).invoke(pane,args);
} catch (final Throwable ignored) {}
With this change, my application compiled.
Of course compiling and running are two different things. Only about 4% of the swing code is actually implemented. The rest of the methods are place holders.
Bill
Re: When can we expect suport for Swing?
Here! Here!
Re: Compiling Java with GCJ
Can gcj compile from a jar file and/or .class files rather than from Java source code? I want to compile
an app which uses a couple of jar files, and recompiling them
from source is hard.
Re: Compiling Java with GCJ
great stuff!
i came from: http://www.rhoads.com/papers/holygrail.jsp
~hugh
Re: Compiling Java with GCJ
Interesting....unfortunately I could not even get HelloWorld to compile using Cynwin.
Ohh well will try it again on my linux machine when I get home.
Keep up the good work.
Re: Compiling Java with GCJ
You need to install the libiconv.a package and add all the missing libraries on the command line. Doesn't seem to all be setup under cygwin.
gcc -c Hello.java
gcc --main=Hello -o Hello Hello.o -l gcj -l iconv -l z
Damn there is still something missing. What is this _WinMain@16 ? Oh well never mind.
Re: Compiling Java with GCJ
that second line should be 'gcj'; not gcc. Then you can leave off all the '-l' options.
Re: Compiling Java with GCJ
I love java, and I can only thank the GCJ team for the very good job they are making. Java, as released by Sun, is not open source and this has limited the language acceptance in the linux world: I can only hope that the GCJ project will solve this! On my side, I will for sure start writing my java code for gcj!
Tanks, and keep up the good work
Enrico
Re: Compiling Java with GCJ
You damn sure my freind....
Unfortunately I am learning by now but one day I will like you :)
Re: Compiling Java with GCJ
You damn sure my freind....
Unfortunately I am learning by now but one day I will like you :)
Tried to compile a simple
Tried to compile a simple "Hello world" program, and the exe created is 4.2 MB !! Whoa ! So I stripped it and it's size went down to 2.1 MB
....
Isn't this some kind of bloat ? It works well tough
that plus has one dll dependency
yea...for me...it was 3.4MB plus a 980KB dll (libiconv2.dll).
With UPX 1.25, the size of the exe is almost 2MB and the dll is 650KB.
Even after strip (strip hello.exe), it's 2.1MB (and it's 640KB after strip and UPX).
in FPC, it's about 20KB (2.0) (1.x is around 8KB or less) before UPX.
so much bloat.
it needs lipo...badly.