Details
-
Type:
Bug
-
Status:
Closed
-
Priority:
Critical
-
Resolution: Fixed
-
Affects Version/s: JRuby 1.2
-
Fix Version/s: JRuby 1.2
-
Component/s: Core Classes/Modules
-
Labels:None
-
Environment:MacOS 10.5.6, JRuby trunk r8497, activerecord 2.2.2 and trunk
-
Testcase included:yes
-
Number of attachments :
Description
Using an activerecord 'to_xml' method on an AR instance crashes JRuby (and debugger).
The JRuby regression happened in a large commit about callbacks on Dec 18:
svn rev:8398
"Grr...I suppose I should have checked this before, but Mongrel still uses CallbackFactory. We need to get them off it so we can delete it some day. Damn you, crufty old dependencies!"
My tests are being run with these gems:
activerecord (2.2.2)
activerecord-jdbc-adapter (0.9)
activerecord-jdbcmysql-adapter (0.9)
Here's the test code:
filename: ar_to_xml.rb
require 'rubygems' require 'activerecord' # create a db named 'my_active_record_test' # GRANT ALL PRIVILEGES ON my_activerecord_test.* to 'rails'@'localhost'; @logger = Logger.new $stderr ActiveRecord::Base.logger = @logger ActiveRecord::Base.colorize_logging = false pool = ActiveRecord::Base.establish_connection( :adapter => RUBY_PLATFORM =~ /java/ ? 'jdbcmysql' : 'mysql', :username => 'rails', :encoding => 'utf8', :database => 'my_activerecord_test' ) ActiveRecord::Schema.define do drop_table :posts if pool.connection.table_exists?(:posts) create_table :posts do |t| t.string :subject t.text :body end end class Post < ActiveRecord::Base; end p = Post.create(:subject => 'first post', :body => 'this is the body') puts p.to_xml
This works fine in MRI. Here's the result in jruby svn r8497
$ jruby ar_to_xml.rb SQL (1.4ms) SET SQL_AUTO_IS_NULL=0 -- drop_table(:posts) SQL (1.6ms) DROP TABLE `posts` -> 0.0025s -> 0 rows -- create_table(:posts) SQL (25.9ms) CREATE TABLE `posts` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, `subject` varchar(255), `body` text) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin -> 0.0314s -> 0 rows SQL (2.1ms) INSERT INTO `posts` (`subject`, `body`) VALUES('first post', 'this is the body') Entities$PrimitiveEntityMap:471:in `<init>': java.lang.NoClassDefFoundError: org/jruby/util/collections/IntHashMap from Entities$LookupEntityMap:552:in `<init>' from Entities:754:in `<init>' from Entities:402:in `<clinit>' from FastXsService:28:in `fast_xs' from FastXsServiceCallback$fast_xs_FS0:-1:in `call' from org.jruby.runtime.callback.FastInvocationCallback:55:in `execute' from org.jruby.internal.runtime.methods.FullFunctionCallbackMethod:69:in `call' from org.jruby.internal.runtime.methods.DynamicMethod:226:in `call' from org.jruby.internal.runtime.methods.DynamicMethod:203:in `call' from org.jruby.internal.runtime.methods.AliasMethod:60:in `call' from org.jruby.runtime.callsite.CachingCallSite:253:in `cacheAndCall' from org.jruby.runtime.callsite.CachingCallSite:72:in `call' from org.jruby.ast.CallNoArgNode:61:in `interpret' from org.jruby.ast.NewlineNode:100:in `interpret' from org.jruby.internal.runtime.methods.DefaultMethod:156:in `interpretedCall' from org.jruby.internal.runtime.methods.DefaultMethod:133:in `call' from org.jruby.internal.runtime.methods.DefaultMethod:246:in `call' from org.jruby.runtime.callsite.CachingCallSite:273:in `cacheAndCall' from org.jruby.runtime.callsite.CachingCallSite:112:in `call' from org.jruby.ast.FCallOneArgNode:36:in `interpret' from org.jruby.ast.CallTwoArgNode:59:in `interpret' from org.jruby.ast.NewlineNode:100:in `interpret' from org.jruby.internal.runtime.methods.DefaultMethod:156:in `interpretedCall' from org.jruby.internal.runtime.methods.DefaultMethod:133:in `call' from org.jruby.internal.runtime.methods.DefaultMethod:246:in `call' from org.jruby.runtime.callsite.CachingCallSite:273:in `cacheAndCall' from org.jruby.runtime.callsite.CachingCallSite:112:in `call' from org.jruby.ast.FCallOneArgNode:36:in `interpret' from org.jruby.ast.NewlineNode:100:in `interpret' from org.jruby.ast.CaseNode:108:in `interpret' from org.jruby.ast.NewlineNode:100:in `interpret' from org.jruby.internal.runtime.methods.DefaultMethod:156:in `interpretedCall' from org.jruby.internal.runtime.methods.DefaultMethod:133:in `call' from org.jruby.internal.runtime.methods.DefaultMethod:246:in `call' from org.jruby.runtime.callsite.CachingCallSite:273:in `cacheAndCall' from org.jruby.runtime.callsite.CachingCallSite:112:in `call' from org.jruby.ast.FCallOneArgNode:36:in `interpret' from org.jruby.ast.NewlineNode:100:in `interpret' from org.jruby.ast.EvStrNode:82:in `interpret' from org.jruby.ast.DStrNode:82:in `appendToString' from org.jruby.ast.DStrNode:72:in `buildDynamicString' from org.jruby.ast.DStrNode:64:in `interpret' from org.jruby.ast.CallOneArgNode:57:in `interpret' from org.jruby.ast.IfNode:108:in `interpret' from org.jruby.ast.NewlineNode:100:in `interpret' from org.jruby.ast.BlockNode:67:in `interpret' from org.jruby.runtime.InterpretedBlock:202:in `evalBlockBody' from org.jruby.runtime.InterpretedBlock:153:in `yield' from org.jruby.runtime.Block:120:in `yield' from org.jruby.RubyArray:1533:in `each' from org.jruby.RubyArray$i_method_0_0$RUBYFRAMEDINVOKER$each:-1:in `call' from org.jruby.runtime.callsite.CachingCallSite:263:in `cacheAndCall' from org.jruby.runtime.callsite.CachingCallSite:81:in `callBlock' from org.jruby.runtime.callsite.CachingCallSite:86:in `call' from org.jruby.ast.CallNoArgBlockNode:63:in `interpret' from org.jruby.ast.NewlineNode:100:in `interpret' from org.jruby.ast.BlockNode:67:in `interpret' from org.jruby.internal.runtime.methods.DefaultMethod:156:in `interpretedCall' from org.jruby.internal.runtime.methods.DefaultMethod:133:in `call' from org.jruby.internal.runtime.methods.DefaultMethod:288:in `call' from org.jruby.runtime.callsite.CachingCallSite:293:in `cacheAndCall' from org.jruby.runtime.callsite.CachingCallSite:152:in `call' from org.jruby.ast.FCallTwoArgNode:38:in `interpret' from org.jruby.ast.IfNode:108:in `interpret' from org.jruby.ast.NewlineNode:100:in `interpret' from org.jruby.ast.BlockNode:67:in `interpret' from org.jruby.internal.runtime.methods.DefaultMethod:156:in `interpretedCall' from org.jruby.internal.runtime.methods.DefaultMethod:133:in `call' from org.jruby.internal.runtime.methods.DefaultMethod:183:in `call' from org.jruby.runtime.callsite.CachingCallSite:243:in `cacheAndCall' from org.jruby.runtime.callsite.CachingCallSite:32:in `call' from org.jruby.ast.FCallManyArgsNode:60:in `interpret' from org.jruby.ast.NewlineNode:100:in `interpret' from org.jruby.ast.BlockNode:67:in `interpret' from org.jruby.internal.runtime.methods.DefaultMethod:156:in `interpretedCall' from org.jruby.internal.runtime.methods.DefaultMethod:133:in `call' from org.jruby.internal.runtime.methods.DefaultMethod:204:in `call' from org.jruby.runtime.callsite.CachingCallSite:253:in `cacheAndCall' from org.jruby.runtime.callsite.CachingCallSite:72:in `call' from org.jruby.ast.CallNoArgNode:61:in `interpret' from org.jruby.ast.NewlineNode:100:in `interpret' from org.jruby.ast.BlockNode:67:in `interpret' from org.jruby.ast.IfNode:110:in `interpret' from org.jruby.ast.NewlineNode:100:in `interpret' from org.jruby.ast.BlockNode:67:in `interpret' from org.jruby.ast.BeginNode:79:in `interpret' from org.jruby.ast.InstAsgnNode:87:in `interpret' from org.jruby.ast.OpAsgnOrNode:101:in `interpret' from org.jruby.ast.NewlineNode:100:in `interpret' from org.jruby.internal.runtime.methods.DefaultMethod:156:in `interpretedCall' from org.jruby.internal.runtime.methods.DefaultMethod:133:in `call' from org.jruby.internal.runtime.methods.DefaultMethod:204:in `call' from org.jruby.runtime.callsite.CachingCallSite:253:in `cacheAndCall' from org.jruby.runtime.callsite.CachingCallSite:72:in `call' from org.jruby.ast.VCallNode:81:in `interpret' from org.jruby.ast.CallSpecialArgBlockNode:52:in `interpret' from org.jruby.ast.NewlineNode:100:in `interpret' from org.jruby.ast.BlockNode:67:in `interpret' from org.jruby.internal.runtime.methods.DefaultMethod:156:in `interpretedCall' from org.jruby.internal.runtime.methods.DefaultMethod:133:in `call' from org.jruby.internal.runtime.methods.DefaultMethod:225:in `call' from org.jruby.runtime.callsite.CachingCallSite:263:in `cacheAndCall' from org.jruby.runtime.callsite.CachingCallSite:81:in `callBlock' from org.jruby.runtime.callsite.CachingCallSite:86:in `call' from org.jruby.ast.FCallNoArgBlockPassNode:26:in `interpret' from org.jruby.ast.NewlineNode:100:in `interpret' from org.jruby.internal.runtime.methods.DefaultMethod:156:in `interpretedCall' from org.jruby.internal.runtime.methods.DefaultMethod:133:in `call' from org.jruby.internal.runtime.methods.DefaultMethod:204:in `call' from org.jruby.runtime.callsite.CachingCallSite:253:in `cacheAndCall' from org.jruby.runtime.callsite.CachingCallSite:72:in `call' from org.jruby.ast.CallNoArgNode:61:in `interpret' from org.jruby.ast.IfNode:110:in `interpret' from org.jruby.ast.NewlineNode:100:in `interpret' from org.jruby.ast.BlockNode:67:in `interpret' from org.jruby.internal.runtime.methods.DefaultMethod:156:in `interpretedCall' from org.jruby.internal.runtime.methods.DefaultMethod:133:in `call' from org.jruby.internal.runtime.methods.DefaultMethod:204:in `call' from org.jruby.runtime.callsite.CachingCallSite:253:in `cacheAndCall' from org.jruby.runtime.callsite.CachingCallSite:72:in `call' from ar_to_xml:31:in `__file__' from ar_to_xml:-1:in `load' from org.jruby.Ruby:573:in `runScript' from org.jruby.Ruby:476:in `runNormally' from org.jruby.Ruby:350:in `runFromMain' from org.jruby.Main:214:in `run' from org.jruby.Main:100:in `run' from org.jruby.Main:84:in `main'
The crash happens in when executing line 154 of activerecord's xml_serializer.rb
starting at line 153
def to_xml(options = {}, &block)
serializer = XmlSerializer.new(self, options)
block_given? ? serializer.to_s(&block) : serializer.to_s
end
The debugger actually ends up displaying line 7 of activerecord's serialization.rb
def initialize(record, options = {})
@record, @options = record, options.dup
end
If you have the latest ruby-debug gems you can run this test from the shell and attach a remote debugger from a version 7 instance of NetBeans.
see: http://blogs.sun.com/martink/entry/remote_debugging_debug_whatever_ruby
jruby --debug -S rdebug-ide -p 7000 --stop -- ar_to_xml.rb
The debugger exits with this statement on the console:
Exception in DebugThread loop: undefined method `[]' for nil:NilClass
I have these versions of ruby-debugger installed:
ruby-debug (0.10.3)
ruby-debug-base (0.10.3.1)
ruby-debug-ide (0.4.3)
Well I suppose I should have expected this...it looks like something outside of JRuby is using IntHashMap. I can reinstate the class, but it's been deprecated for quite a while. It's a serious nuisance that it's being used outside of JRuby, but I don't want to break AR. So I will file a separate bug to get AR to stop using it (or to annex it).
Patch attached to reinstate IntHashMap.