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?

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState