How to use Java 5 on the cRIO

Hi!
I know that this is pretty outdated now because … next year everyone will be on the RoboRIO.
But I’m sure there are some of you still playing with cRIOs and practicing and stuff! My team is just transitioning and going to use Java next year for the first time (well, my team is, I just graduated), and so I was teaching them on our cRIO and I was getting very frustrated that it only supports Java 2. Well, technically, source level 1.3, but it compiles down to 1.2. So I fixed it, and everyone can have boxing and unboxing and generics and stuff!

There are only three files to change.

  1. Navigate to your sunspotfrcsdk directory. This is usually in your user directory, e.g. C:\Users\Jimbob\sunspotfrcsdk. Look in the “ant” folder, and open up “compile.xml” in a text editor. Look for where it says
target="1.2"
source="1.3"

and replace it with

target="1.5"
source="1.5"
  1. In the same ant folder, open up preverify.xml. Look for where it says
</exec>
</else>

and then insert in the middle,

</exec>

<exec executable="powershell.exe" dir="@{preverify.dir}">
						<arg value="Get-ChildItem . -Filter *.class -Recurse | Foreach-Object {$bytes  = [System.IO.File]::ReadAllBytes($_.FullName);$offset = 7;$bytes$offset]   = 46;[System.IO.File]::WriteAllBytes($_.FullName, $bytes); }" />
					</exec>

</else>
  1. Start using a modern version of preverify. You can get this from Oracle Java ME SDK 3.*, but since most people won’t want to install that, I’ve also put the executable up on dropbox at https://dl.dropboxusercontent.com/u/16280155/preverify.exe that you can download (32-bit, so it will work for everyone). Put in sunspotfrcsdk/bin, overwriting the existing preverify.exe. If you want to be able to revert, just rename the old one as preverify_old.exe.

And this should do it! The bytecode is pretty much compatible through almost all major versions of Java, excepting where you get to 1.6’s stack map tables or 1.7’s invokedynamic opcode. The major version in the compiled class files is set as 49 which the romizer compiler rejects, but the powershell script just overwrites that byte and it all works as far as I can tell.

You might still have some issues with NetBeans highlighting your code and saying that it’s set to source version 1.3; I can’t find where this is set, yet, in order to get it to cooperate. If anyone else can figure it out, let me know! Now everyone can start using ArrayList<T> again. :slight_smile:

Isn’t this discouraged because the JVM itself is not the standard HotSpot JVM build for 1.5? It is the Squawk VM that runs the CLDC 1.1 (1.2?) implementation? I mean the whole reason is that in many cases you are having fun balancing memory when you want to write larger implementations. Hence CLDC, the cRIO is quite often very hard pressed for memory.

Not to say it is impossible for the cRIO to handle Generics, Autoboxing and Lists but I had always thought the reason for this was the cost of what is already implemented in the FRC SDK and the fact that Squawk VM does not have the same capabilities as HotSpot but with a smaller memory footprint.

It has been a simple task with Ant to change its build.xml but if this is fine, what prevents me from moving on to higher Java ME versions?

I am curious, really, if you have tried running that code at all on a robot in a meaningful way, because I feel this would be incompatible with the Squawk VM. But I assume you havent since you said you ARE switching.

The choice as to which Java version to run on vxWorks was made by Sun Research themselves. They spent a decent amount of time getting the VM to run and hooked to the OS. I suspect that they chose version 2/3 and not more modern versions for good reason. Brad Miller helped them with the work and may know more of the details.

Sorry, but I highly doubt that the suggested change will work reliably.

Greg McKaskle

It does work reliably in terms of language features, however – the compiled bytecode from Java 2 through Java 5 is fully backwards compatible; all the language features such as varargs, foreach loops, generics, and boxing/autoboxing are handled by the compiler and translated into the same bytecode. The only one I’m aware of as not being quite compatible is assertions, I’m trying to figure out what’s missing there. (Something wrong with how the constant pool is accessed in <clinit>.)

Since they’re essentially just syntactic sugar for something else, they aren’t actually adding overhead in terms of memory/runtime. Obviously you can’t use foreach loops on non-array objects until you’ve added the collections API, or at least Iterator/Iterable, but once you /have/ put those in it will link against them correctly and work. (you can already use them over arrays, because that gets translated into just an index.)

It’s probably unwise to just drop in all of java.util.* to your project, but certainly adding Iterator/Iterable/List/AbstractList/ArrayList/Map/AbstractMap/HashMap will make some people happier, I think, and it won’t add much in terms of memory usage.

Matthew, I haven’t run full-scale quantities of code, but since I know the bytecode and I know that features such as generics don’t actually have any performance change, I feel very confident when I say they won’t negatively influence it. As for why higher JavaME versions become incompatible, at least in later versions of Java there is eventually an invokedynamic opcode added (for lambdas) that will definitely not work. You may also run into trouble with the compiler producing stack map tables that the romizer may or may not accept. I didn’t try any higher versions, though, since I felt like Java 5 was “good enough” to feel like modern Java in a lot of ways.

Edit: As far as I know a main reason for opting to use an earlier version of Java would probably be the modifications to the Java Memory Model that imposed certain restrictions on how multithreading should work. The performance hasn’t fundamentally changed.

Our team has had success with using RetroTranslator to let us write our core libraries in Java 5 and downgrade them to run on the cRIO - and it did, actually, work pretty reliably for us last year.
It has a few issues with anonymous classes, so we don’t use in for our main robot coding, but it proved useful to write the CCRE’s primary abstractions.
We also rewrote a large part of the collections library to run, though probably you could drop in the recent JRE implementations of this library if you aren’t worrying about licensing issues.

Additionally, supposedly the eclipse compiler can target an earlier bytecode version than source version, which might be a more reliable method of doing this kind of retargetting.