Skip to end of metadata
Go to start of metadata

Java Support Overview

JRuby has a new interface for loading and using Java classes as of version 0.5.2.

Goals

To make Java classes as easy to use as possible they should ideally behave just like Ruby classes. In most cases this works flawlessly, but when compromises have to be made they are not always right for every purpose. The old Java support solved the first problem, but didn't offer a solution when more control was needed. The design goals for the new Java support was to keep the simplicity of the old java support, but allow for low-level access with full control whenever needed.

Design

Java support was split into two halves, "low-level" and "high-level". The low-level is implemented in Java and provides a thin wrapper over Java's reflection classes (java.lang.reflection.* and java.lang.Class). The high-level is built on top of this, implemented entirely in Ruby.

Low-level

It is probably easier to understand this API if you are familiar with the Java Reflection API.

All Java objects used in Ruby code are wrapped in JavaObject instances. On their own they can't do very much. But used together with instances of JavaMethod, a method call can be made:

java_method.invoke(java_object, arg1, arg2)

JavaClass, JavaMethod and JavaField are used to get information about Java classes. Which methods and fields do they have, what interfaces do they implement, are they final, static or public? Everything that is possible to do in Java itself should be possible to do with the low-level API, albeit in an awkward way.

High-level

A raw JavaObject is not very useful for scripting. So instead we use a JavaProxy, which has methods corresponding to the real Java methods on the JavaObject. Every call to one of those methods is implemented as a call though the low-level 'invoke' method. When using the high-level API you will rarely come across a JavaObject, since every returned value is automatically wrapped in a JavaProxy.

The only thing the script developer has to do is to load the high-level support and include the wanted Java packages into a Ruby class or module:

require 'java'                 # Load the high-level Java support

module Foo
 include_package 'java.util'  # Classes in java.util will be
# available in this module

 r = Random.new               # Create instance of java.util.Random

 puts r.nextInt               # Write a random integer to output

end

As of ruby 0.8, it is possible to rewrite the following exmaple as follows:

require 'java'

include_class 'java.util.Random'

r = Random.new

puts r.nextInt

In both examples the 'int' returned from the Java method nextInt() is automatically converted into a Fixnum. These conversions are automatically done for numbers, booleans and strings, both to and from Java. However, it does *not* convert collection and array types like the old Java support did.

Unlike the first example, the second example is importing Random directly into the top-level (whereas, the first requires you import a whole package into a non-top-level module).

  • No labels