Skip to content

JRuby Reference

Sean Story edited this page Dec 13, 2021 · 16 revisions

Table of Contents

require 'path/to/file.jar'

require can take a path to a jar file. It searches the JRuby $LOAD_PATH for the file.

require 'java'

A special `require 'java'` directive in your file will give you access to any bundled Java libraries (classes within your java class path). However, this will not give you access to any non-bundled libraries.

#each

JRuby supports calling the `#each` method on Enumerable objects

Name translations

Java: org.foo.department.Widget
Ruby: Java::OrgFooDepartment::Widget

For the top-level Java packages java, javax, org, and com you can type in a fully qualified class name:

java_import java.lang.System

You can use your own top-level package names by adding a def:

def edu
  Java::Edu
end

java_import edu.example.MyClass

Importing a package into a class or module

module M
 include_package "org.xxx.yyy"
 # now any class within "org.xxx.yyy" will be available within
 # this module, ex if "org.xxx.yyy.MyClass" exists
 # a = MyClass.new
end
Note that there are issues with include_package, discussed at http://jira.codehaus.org/browse/JRUBY-5558.

enums

Available as constants:
ms_constant_value = java.util.concurrent.TimeUnit::MILLISECONDS

Alternative Names and Beans Convention

You can use underscore-separated names in addition to camel-cased names. These two call the same method:

java.lang.System.currentTimeMillis
java.lang.System.current_time_millis

JRuby also translates methods following the 'beans-convention':

x.getSomething            becomes   x.something
x.setSomething(newValue)  becomes   x.something = new_value
x.isSomething             becomes   x.something?

Constructors

JavaClass.new or JavaClass.new(x,y,z) generally work as expected. If you wish to select a particular constructor by signature use reflection:

 # Get the the three-integer constructor for this class
 construct = JavaClass.java_class.constructor(Java::int, Java::int, Java::int)
 # Use the constructor
 object = construct.new_instance(0xa4, 0x00, 0x00).to_java

java_class

returns the Java class of an object. Use this for methods expecting a java Class object:
DoSomethingWithJavaClass(MyJavaClass.java_class)
java_kind_of?
works like the `instanceof` operator.
java_object
returns the underlying Java object. This is useful for reflection.
java_send
overrides JRuby's dispatch rules and forces the execution of a named Java method on a Java object. This is useful for Java methods, such as `initialize`, with names that conflict with built-in Ruby methods.
With the `java_method` method you can get a reference to any overloaded Java method as a Ruby Method object:
 # get a bound Method based on the add(int, Object) method from ArrayList
 add = list.java_method :add, [Java::int, java.lang.Object]
 add.call(0, 'foo')

Similarly, an Unbound method object can be retrieved:

 # get an UnboundMethod from the ArrayList class:
 toString = ArrayList.java_method :toString
 toString.bind(list).call # => [foo, foo]

java_method

retrieves a bound or unbound handle for a Java method to avoid the reflection inherent in `java_send`.

declared_method

@mgr = javax.media.rtp.RTPManager.newInstance
localhost = java.net.InetAddress.getByName("127.0.0.1")
localaddr = javax.media.rtp.SessionAddress.new(localhost, 21000, localhost, 21001)
method = @mgr.java_class.declared_method(:initialize, javax.media.rtp.SessionAddress )
method.invoke @mgr.java_object, localaddr.java_object

Type conversion

See CallingJavaFromJRuby

Arrays

constructs a Java array from a Ruby array:
[1,2,3].to_java
=> [Ljava.lang.Object;@1a32ea4

By default, `to_java` constructs `Object` arrays. You can specify the parameter with an additional argument which can either be a symbol or a primitive class like `Java::double`

["a","b","c"].to_java(:string)
=> [Ljava.lang.String;@170984c

[1, 2, 3.5].to_java Java::double
=> [D@9bc984

Constructing Empty Java Arrays

Use the `[]` method of the primitive types in the Java module:
bytes = Java::byte[1024].new # Equivalent to Java's bytes = new byte[1024];

Ruby String to Java Bytes and back again

bytes = 'a string'.to_java_bytes
=> #<#<Class:01x9fcffd>:0x40e825 @java_object=[B@3d476c>

string = String.from_java_bytes bytes
=> "a string"

Java InputStream to a ruby IO object

io = input_stream.to_io # works for InputStreams, OutputStreams, and NIO Channels

Interfaces

JRuby classes can implement more than one Java interface. Use include to implement an interface:
class SomeJRubyObject
  include java.lang.Runnable
  include java.lang.Comparable
end

When calling a method that expects an interface, JRuby checks if a block is passed and automatically converts the block to an object implementing the interface.

To have a generated Java class (via `jrubyc --java(c)`) implement an interface, use `java_implements` instead

class SomeJRubyObject
  java_implements 'java.lang.Runnable'
  java_implements 'java.lang.Comparable'
end

Exceptions

 begin
   java.lang.Integer.parse_int("asdf")
 rescue java.lang.NumberFormatException => e
   puts "Failed to parse integer: #{e.message}"
 end
 begin
   raise java.lang.IllegalArgumentException.new("Bad param")
 rescue java.lang.IllegalArgumentException => e
   puts "Illegal argument: #{e}"
 end

Or

 begin
   raise Java::JavaLang::IllegalArgumentException.new("Bad param")
 rescue Java::JavaLang::IllegalArgumentException => e
   puts "Illegal argument: #{e}"
 end

You can also create and throw Ruby exceptions from Java:

// To construct one of the core error types, use the appropriate method on org.jruby.Ruby
RaiseException rubyThrowable = runtime.newArgumentError("some message")

// To construct a non-core error type, construct it from Ruby and call toThrowable
IRubyObject exception = runtime.evalScriptlet("Mongo::GssapiNative::Error.new(\"" + message + "\")");
throw ((RubyException) exception).toThrowable();

// Or acquire a reference to the class and use newInstance
RubyClass cls = runtime.getClass("Mongo::GssapiNative::Error");
RubyString msg = RubyString.newString(context.runtime, message);
throw ((RubyException) cls.newInstance(context, msg, Block.NULL_BLOCK)).toThrowable();

synchronize

a synchronize method is provided on every wrapped Java object. For example:
 synchronized(obj) {
     obj.wait(1000); 
 }

is implement like this in Ruby:

 obj.synchronized do
   obj.wait 1000
 end

java_require

Normally, `jrubyc --java(c)` will include the complete source of your script in the compiled class, but often you may want to keep the source on disk or generate multiple classes that all come from the same file. To do this, add a java_require line (plus a require 'java' line to enable Java support in the Ruby code) that specifies what filename to load. The filename specified is loaded using normal Ruby 'require' semantics.
 require 'java'
 java_require 'my_foo'
 class Foo
   def bar(a,b)
     puts a + b
   end
 end

java_signature

 require 'java'
 java_require 'my_foo'
 class Foo
   java_signature 'void bar(int, int)'
   def bar(a,b)
     puts a + b
   end
   # using annotations
   java_signature '@java.lang.Deprecated void baz(int, int)'
   def baz(a,b)
     puts a + b
   end
 end

java_field

 require 'java'

 class Foo
   java_field 'java.lang.String foo'
   # using annotations
   java_field '@javafx.fxml.FXML int myField'
 end

java_package

 require 'java'
 java_require 'my_foo'
 java_package 'com.example'

 class Foo; end

java_annotation

(deprecated for methods and fields as of 9.3) Use java_signature or java_field in new code when dealing with methods and fields, respectively
Adds Java annotations to a JRuby class or method.
 require 'java'
java_import 'javax.ws.rs.Path'
java_import 'javax.ws.rs.GET'
java_import 'javax.ws.rs.Produces'

java_package 'com.headius.demo.jersey'
java_annotation 'Path("/helloworld")'
class HelloWorld
  # DEPRECATED: java_annotation 'GET'
  # DEPRECATED: java_annotation 'Produces("text/plain")'
  java_signature '@GET @Produces("text/plain") void cliched_message()'
  def cliched_message
    "Hello World"
  end
end
Clone this wiki locally