我有一个JRuby引擎,它从Ruby类调用方法“run_code”。 “run_code”方法调用IRB命令并捕获其输出。
方法“run_code”的第一次调用每次都能正常工作。
第二次调用给了我这些错误:
(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)
第三次调用给了我这些错误:
(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
错误。
答案 0 :(得分:0)
我最初建议做这样的事情,因为它在过去为我修复了同样的错误:
ScriptingContainer container = new ScriptingContainer();
try {
Reader reader = new FileReader(myEngine);
// rest of your code here...
} finally {
container.terminate();
}