Embedded Java with GCJ

You don't always need a Java Virtual Machine to run Java in an embedded system.
GCJ Development

After building the cross compiler and root filesystem, building your GCJ application will be a bit anticlimactic. We'll start with the traditional hello world:


Class hello {
 Static public void main(String argc[]) {
   System.out.println("hello from GCJ");
 }
}

Following Java convention, this class resides in the hello.class file. To compile the file, enter:


powerpc-750-linux-gnu-gcj hello.class --main=hello -o hello-java

What's going on with --main=hello? Any class could define a method with a suitable entry point. The --main=hello option tells the linker to use the main method in the hello class when linking. Leaving off this option results in a link error, “undefined reference to main”, which, to the uninitiated, is confusing, because your class contains a main.

Download this file to the target and run it from the chrooted shell. You'll see:


# ./java-test
Hello from GCJ

At this point, development carries on much like any other Java project, with the exception of invoking the GCJ cross compiler instead of the native javac compiler.

Conserving Space

In this example, the root filesystem weighs in at more than 20MB. Because many embedded systems use Flash memory, which is considerably more expensive on a per-megabyte basis than disk-based storage systems, a minimally sized root filesystem is frequently an important business requirement. One easy way to reduce the size of your root filesystem is to link your application statically. Although this may seem counterintuitive at first, as you'll have an extra copy of libc code in your application, recall that libgcj.so contains the entire Java standard library. Most applications use a fraction of the standard Java library, so using static linking is a great way to winnow out the unused code in the library. Just be sure to strip the resulting binary; otherwise, you'll be shocked at the size due to the amount of debugging information in libgcj.so.

Wrapping Up

From the article, you've seen that creating software for an embedded system using GCJ is something that can be reasonably accomplished using tools already present in the Open Source community. Although there are a few minor nits, configuring the root filesystem doesn't require a heroic effort; you just need to get a few different libraries from what you otherwise would need. For applications requiring a smaller root filesystem, we've seen how you can use static linking of your application to reduce the root filesystem greatly. In short, GCJ is a practical solution for using Java on a resource-constrained embedded system—worthy of consideration for your next project.

Gene Sally has been working with Linux in one form or another for the last ten years. These days, Gene focuses his attention on helping engineers use Linux on embedded targets. Feel free to contact Gene at gene.sally@gmail.com.

______________________

Comments

Comment viewing options

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

Commission Blueprint

John Maven's picture

I compiled it and it didn't work. I repeat: it did NOT work.

Rather unfortunate.

Typographical Error

lumkichi's picture

While everyone noted the sample "hello" program does not compile as-is, I'm surprised no one expressed why but instead offered alternatives. The reason the sample program does not compile is because there are two typographical errors in it (I'm sure it was unintended - an artifact as a result of using a Word Processor such as MS Word).


Class hello {
  Static public void main(String argc[]) {
    System.out.println("hello from GCJ");
  }
}

The keywords "Class" and "Static" should not be capitalized. It should look like this:


class hello {
  static public void main(String argc[]) {
    System.out.println("hello from GCJ");
  }
}

The capitalization changed the keywords "class" and "static" into Object names. The compiler was trying to find a "Class.class" to make a "Class" object named "hello" and couldn't. The same with "Static."

This is a great article, and the author did a great job writing it. Unfortunately formatting the document (and the code, especially) is a bear. Just to get the code snippet above look the way is does was a lot of work - way more work than just typing.

~lum

Won't compile with gcj-4.1 on my Debian

Olivier Berger's picture

Hmmm... maybe this is not related to the specifics of embedded environment at all, but I noticed that the hello world example won't compile with "gcj-4.1 hello.class --main=hello -o hello-java" on my Debian testing system :

hello.class:1: error: Class or interface declaration expected.
Class hello {
^
hello.class:2: error: Class or interface declaration expected.
Static public void main(String argc[]) {
^
hello.class:3: error: Class or interface declaration expected.
System.out.println("hello from GCJ");
^
hello.class:4: error: Class or interface declaration expected.
}
^
hello.class:5: error: Class or interface declaration expected.
}
^
5 errors

Dunno what's wrong

After a quick search on the

Olivier Berger's picture

After a quick search on the net, I found that writing this way, it compiles :


public class hello {
static public void main(String argc[]) {
System.out.println("hello from GCJ");
}
}

This worked for me:class

Anonymous's picture

This worked for me:

class hello
{
static public void main( String argc[] )
{
System.out.println( "hello from GCJ" );
}
}

Notice that none of the keywords like "class" are capitalized. Also, typical naming convention for java is to call the source file hello.java and using the javac command turns the byte code into hello.class We're not using javac, so there won't be a hello.class file. So, if you name your file this way, the compile step would be:

gcj hello.java --main=hello -o hello-java

Hope this helps.

After reading this article, I

mathews's picture

After reading this article, I just realized how we can simplify our seemingly complicated problems which in fact can actually be solved very easily! It actually helps us to use GCJ which is really a part of the GCC compiler suite, in a Linux project! The advantage is that it can be code with a high-level language like Java! It gives us a detailed tutorial about its advantages and pitfalls, the host and target configuration and lastly if you are happy with what you have read, the step by step instructions to build your GCJ cross compiler! Very cool and informative read indeed!!RFID Tags

Statically linking

Dan's picture

I tried statically linking a simple "Hello, World!" program but received the following error:

/usr/bin/ld: cannot find -lgcj

Here's the command I used to compile:

gcj -static-libgcj -o hello --main=hello hello.java

Any ideas?

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