Rubyクラスからメソッド「run_code」を呼び出すJRubyエンジンがあります。「run_code」メソッドはIRBコマンドを呼び出し、その出力をキャプチャします。
メソッド「run_code」の最初の呼び出しは、毎回正常に機能します。
2番目の呼び出しは私にこれらのエラーを与えます:
(Errno::EBADF) Bad file descriptor
Caused by: org.jruby.embed.InvokeFailedException: (Errno::EBADF) Bad file descriptor
at org.jruby.embed.internal.EmbedRubyObjectAdapterImpl.call(EmbedRubyObjectAdapterImpl.java:406)
at org.jruby.embed.internal.EmbedRubyObjectAdapterImpl.callMethod(EmbedRubyObjectAdapterImpl.java:3
33)
at org.jruby.embed.ScriptingContainer.callMethod(ScriptingContainer.java:1334)
at org.apache.hadoop.hbase.master.ShellEndPoint.commandResponse(ShellEndPoint.java:87)
at org.apache.hadoop.hbase.master.ShellEndPoint.doGet(ShellEndPoint.java:114)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1221)
at org.apache.hadoop.http.HttpServer$QuotingInputFilter.doFilter(HttpServer.java:835)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1212)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:399)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:450)
at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:928)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:549)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
Caused by: org.jruby.exceptions.RaiseException: (Errno::EBADF) Bad file descriptor
Caused by:org.jruby.exceptions.RaiseException: (Errno::EBADF) Bad file descriptor
at org.jruby.RubyIO.initialize(org/jruby/RubyIO.java:981)
at org.jruby.RubyIO.new(org/jruby/RubyIO.java:868)
at Engine.run_code(<script>:28)
3番目の呼び出しは私にこれらのエラーを与えます:
(NoMethodError) undefined method `to_i' for #<StringIO:0x128ef465
Problem accessing /shell. Reason:
(NoMethodError) undefined method `to_i' for #<StringIO:0x128ef465>
Caused by: org.jruby.embed.InvokeFailedException: (NoMethodError) undefined method `to_i' for StringIO:0x128ef465;
at org.jruby.embed.internal.EmbedRubyObjectAdapterImpl.call(EmbedRubyObjectAdapterImpl.java:406)
at org.jruby.embed.internal.EmbedRubyObjectAdapterImpl.callMethod(EmbedRubyObjectAdapterImpl.java:3
33)
at org.jruby.embed.ScriptingContainer.callMethod(ScriptingContainer.java:1334)
at org.apache.hadoop.hbase.master.ShellEndPoint.commandResponse(ShellEndPoint.java:87)
at org.apache.hadoop.hbase.master.ShellEndPoint.doGet(ShellEndPoint.java:114)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1221)
at org.apache.hadoop.http.HttpServer$QuotingInputFilter.doFilter(HttpServer.java:835)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1212)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:399)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:450)
at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:928)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:549)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
Caused by: org.jruby.exceptions.RaiseException: (NoMethodError) undefined method `to_i' for #<Str
ingIO:0x128ef465>
Caused by:org.jruby.exceptions.RaiseException: (NoMethodError) undefined method `to_i'
for #<StringIO:0x128ef465>
at Engine.run_code(<script>:12)
私のJavaコードは次のようになります:
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jruby");
ScriptingContainer container = new ScriptingContainer();
Reader reader = new FileReader(myEngine);
try {
receiver = engine.eval(reader);
ob = container.callMethod(receiver,"run_code",command);
response = ob.toString();
} catch(ScriptException e) {
LOG.debug(e.getMessage());
response ="ERROR";
}
私のルビーコードは次のようになります。
require 'stringio'
require 'irb'
require 'hirb'
class Engine
extend Shell
def initialize()
@binding = Kernel.binding
end
def run_code(code)
# run something
stdout_id = $stdout.to_i
$stdout = StringIO.new
cmd = <<-EOF
$stdout = StringIO.new
begin
#{code}
end
EOF
begin
result = Thread.new { Kernel.eval(cmd, @binding) }.value
rescue SecurityError
return "illegal"
rescue Exception => e
return e
ensure
output = get_stdout
$stdout = IO.new(stdout_id)
end
return output
end
private
def get_stdout
raise TypeError, "$stdout is a #{$stdout.class}" unless $stdout.is_a? StringIO
$stdout.rewind
$stdout.read
end
end
module Kernel
@shell = Shell::Shell.new(@hbase, @formatter)
# Add commands to this namespace
@shell.export_commands(self)
@formatter = Shell::Formatter::Console.new
# Setup the HBase module. Create a configuration.
@hbase = Hbase::Hbase.new
# Setup console
@shell = Shell::Shell.new(@hbase, @formatter)
# Add commands to this namespace
@shell.export_commands(self)
# Add help command
def help(command = nil)
@shell.help(command)
end
# Backwards compatibility method
def tools
@shell.help_group('tools')
end
end
何が問題なのか知っていますか?
新しい$stdoutオブジェクトを作成する代わりに、古いオブジェクトへの参照を保持しました。今それは私に与えます
javax.script.ScriptException: org.jruby.exceptions.RaiseException: (Errno::
EBADF) Bad file descriptor
エラー。