简体   繁体   中英

Calling Java code snippet from JRuby?

How can I call a Java code snippet from JRuby code? My code snippet is really short, actually it's just a set of a few Java statements.

Explained here on how to call existing Java code from JRuby. The most basic usage:

require 'java'
java.lang.System.out.println("Hello, world!")

As a bit more complex example, if you want to import your arbitrary package (say, 'foo.bar.baz') from a JAR, you can do this:

require 'java'
require 'foobarbaz.jar'
def foo
  Java::Foo
end
shiny_thingy = foo.bar.baz.Thingy.new("Shiny")
shiny_thingy.shine()

If you want to evaluate a string as if it was Java, you would need to compile it first; you can use the techniques in this question , but Java generally frowns on autogenerated code, and it is not trivial to do it. Or you can translate it into JRuby, calling Java classes as described above, and skip the compilation issue.

We might be able to help better if we knew what your snippet consisted of.

EDIT: Here is the adaptation of the linked code that will instantiate an arbitrary class. Be aware that it will create .class files, which is AFAIK inevitable when a compilation step is involved. The code assumes a subdirectory named tmp exists; adapt to your use case.

shiny_source = <<-EOF
  package foo.bar.baz;
  public class Shiny {
    public Shiny() {
      System.out.println("I'm shiny!");
    }
  }
EOF

require 'java'
java_import javax.tools.SimpleJavaFileObject
java_import java.net.URI

class JavaSourceFromString < SimpleJavaFileObject
  def initialize(name, code)
    uri = "string:///" + name.gsub('.', '/') + Kind::SOURCE.extension
    super URI.create(uri), Kind::SOURCE
    @code = code
  end

  def getCharContent(ignore_encoding_errors)
    @code
  end
end

java_import javax.tools.ToolProvider
java_import java.io.StringWriter
java_import java.net.URL
java_import java.net.URLClassLoader

compilation_path = java.nio.file.Paths.get('tmp').to_absolute_path.to_s
jc = ToolProvider.get_system_java_compiler
raise "Compiler unavailable" unless jc

jsfs = JavaSourceFromString.new('foo.bar.baz.Shiny', shiny_source)
file_objects = [jsfs]
ccl = java.lang.Thread.current_thread.get_context_class_loader
classpath = ccl.getURLs.to_a.join(java.io.File::pathSeparator)
options = ['-d', compilation_path, '-classpath', classpath]
output = StringWriter.new
success = jc.get_task(output, nil, nil, options, nil, file_objects).call
raise output unless success

url = URL.new("file:" + compilation_path + "/")
ucl = URLClassLoader.new_instance([url].to_java(URL))
shiny_class = ucl.load_class('foo.bar.baz.Shiny')
shiny_class.new_instance

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM