代码之家  ›  专栏  ›  技术社区  ›  user626528

从JRuby调用Java代码片段?

  •  0
  • user626528  · 技术社区  · 11 年前

    如何从JRuby代码中调用Java代码片段?我的代码片段很短,实际上它只是一组Java语句。

    1 回复  |  直到 11 年前
        1
  •  2
  •   Community Mohan Dere    9 年前

    解释 here 关于如何从JRuby调用现有Java代码。最基本的用法:

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

    作为一个更复杂的示例,如果您想从JAR导入任意包(例如,“foo.bar.baz”),可以执行以下操作:

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

    如果您想像Java那样计算字符串,则需要首先编译它;您可以在 this question ,但Java通常不喜欢自动生成的代码,这样做并不简单。或者您可以将其转换为JRuby,如上所述调用Java类,并跳过编译问题。

    如果我们知道你的代码片段是由什么组成的,我们可能会提供更好的帮助。

    编辑:这里是将实例化任意类的链接代码的改编。请注意,它将创建 .class 文件,当涉及编译步骤时,这是AFAIK不可避免的。代码假定一个子目录名为 tmp 存在;适应您的用例。

    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