History | Log In     View a printable version of the current page.  
Issue Details (XML | Word | Printable)

Key: JRUBY-778
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Blocker Blocker
Assignee: Charles Oliver Nutter
Reporter: R. Mark Volkmann
Votes: 1
Watchers: 2
Operations

If you were logged in you would be able to see more operations.
JRuby

basic Swing usage causes SystemStackError

Created: 05/Apr/07 09:39 AM   Updated: 06/May/07 09:49 PM
Component/s: Java Integration
Affects Version/s: JRuby 0.9.8
Fix Version/s: JRuby 1.0.0RC1

Time Tracking:
Not Specified

File Attachments: 1. File jruby_778_diagnostic.rb (0.6 kb)
2. File jruby_version_check.rb (0.2 kb)

Environment: Mac OS X
Issue Links:
Related
 
Supercedes
 
dependent
 


 Description  « Hide
The following simple code results in "stack level too deep (SystemStackError)". This happens in 0.9.8 and in the trunk on 4/5/07.

require 'java'

class MyFrame < javax.swing.JFrame
def initialize
super("Hello Swing!")
pack
end
end

MyFrame.new.visible = true



 All   Comments   Work Log   Change History      Sort Order: Ascending order - Click to sort in descending order
Bill Dortch - 05/Apr/07 10:07 AM
This seems to be OS-dependent; the example works for me in WinXP/Java6/trunk.

Wayne Meissner - 05/Apr/07 10:43 AM
It might be JDK version dependent. On both Linux & MacOSX, it works fine with JDK1.6.0, but fails with SystemStackError on JDK 1.5.0.

Charles Oliver Nutter - 05/Apr/07 12:07 PM
This is pretty severe...we need to tidy up issues like this for 0.9.9

Stephen Bannasch - 08/Apr/07 01:12 PM
This post from the jruby-user list might provide a clue:

At 1:49 PM -0500 3/18/07 on the jruby-user list Micah Martin <micah@8thlight.com wrote:

I've been digging into the code.... It has something to do with the __jcreate! method when constructing the ConcreteProxy. There is a block that seems to get called for every method on the Panel class. It ends up in infinite recursion around the method "insets". I've been debugging it for a while but to be honest, I haven't been able to figure out what's causing the infinite recursion or what exactly that block of code is trying to accomplish. Any hints would be appreciated.

def JavaUtilities.setup_java_subclass(subclass, java_class)

  1. add new class-variable to hold the JavaProxyClass instance
    subclass.class.send :attr, :java_proxy_class, true

subclass.send(:define_method, "__jcreate!") {|*args|
constructors = self.class.java_proxy_class.constructors.select {|c| c.arity == args.length }
raise NameError.new("wrong # of arguments for constructor") if constructors.empty?
args.collect! { |v| Java.ruby_to_java(v) }
self.java_object = JavaUtilities.matching_method(constructors, args).new_instance(args) { |proxy, method, *args|
args.collect! { |arg| Java.java_to_ruby(arg) }

                                          1. This is where recursion kicks in
                                            result = __jsend!(method.name, *args)
                                            Java.ruby_to_java(result)
                                            }
                                            }

Micah


This is the code in question:

require 'java'

class MyPanel < java.awt.Panel
end

frame = java.awt.Frame.new("test frame")
panel = MyPanel.new
frame.add(panel)

frame.pack
frame.show


Jonathan Paisley - 10/Apr/07 09:23 AM
Further info:

The problem is triggered because Container#getInsets() just delegates to Container#insets(). When Container#insets is called, the Ruby proxy is invoked. This method is incorrectly bound to #getInsets() rather than #insets, and so infinite recursion results.

I suspect the difference in behaviour seen between JDK5 and JDK6 is due to the different order of methods returned via reflection. Therefore, it's probably the case that the ruby method 'insets' that's declared as an alias of the property getter 'getInsets' stomps over the real 'insets' method (in JDK5).

Seems like a proper definition of the rules needs to be figured out, and when the proxy class is created those rules must be followed.

For example, when defining a friendly ruby property alias 'foo' for java method 'getFoo', this should only be used if there's not a real java method called 'foo'.


Bill Dortch - 12/Apr/07 04:38 PM
As Jonathan notes, this appears to be a bug (oversimplification?) in JavaClass#define_instance_methods_for_proxy.

Here's another example, from Micah Martin on jruby-user:

On 4/12/07, Micah Martin <micah@8thlight.com> wrote:

    ************ JAVA CODE **********
    public class MyClass {
            public void open() {
                    System.out.println("open()");
            }

            public boolean isOpen() {
                    System.out.println("isOpen()");
                    return false;
            }
    }


    ********** JRUBY CODE ***********
    require 'java'
    include_class 'MyClass'
    mine = MyClass.new

    mine.open
    mine.is_open
    mine.open?


    ********** OUTPUT *****************
    isOpen()
    isOpen()
    isOpen()


    Why is the open() method getting lost?  How do I call it from JRuby?

    I'm on mac os x 10.4.9, Java 1.5.

    Micah

Charles Oliver Nutter - 18/Apr/07 03:21 AM
I just tried this on JRuby trunk (3494) and the original hello swing app started up ok. Can y'all re-test this? I know we have some additional fixes coming from Bill for these sorts of things, but at least the original case appears to work for me on OS X.

Stephen Bannasch - 18/Apr/07 07:49 PM
Mac6S 10.4.9, Java 1.5.0_07-164
updated to trunk: 3499
compiled new jruby with 'ant'
ran my shell script:
JRUBY_HOME=`pwd`
export JRUBY_HOME
PATH=`pwd`/bin:$PATH
export PATH

Here's the program helloswing.rb:

require 'java'

class MyFrame < javax.swing.JFrame
  def initialize
    super("Hello Swing!")
    pack
  end
end

MyFrame.new.visible = true

Here are the errors reported:

$ jruby helloswing.rb
2007-04-18 20:42:03.064 java[2076] CFLog (0): CFMessagePort: bootstrap_register(): failed 1103 (0x44f), port = 0x18403, name = 'java.ServiceProvider'
See /usr/include/servers/bootstrap_defs.h for the error codes.
2007-04-18 20:42:03.065 java[2076] CFLog (99): CFMessagePortCreateLocal(): failed to name Mach port (java.ServiceProvider)
/Users/stephen/dev/jruby-trunk/jruby/src/builtin/javasupport.rb:128 warning: already initialized constant EXIT_ON_CLOSE
helloswing.rb:9:in `initialize': invokee not a java object (TypeError)
        from helloswing.rb:9:in `new'
        from helloswing.rb:9

The first three errors also appear when sucessfully running: samples/swing.rb .


Charles Oliver Nutter - 18/Apr/07 09:50 PM
I'm pretty sure the first two are a Mac thing...I see them too, and I don't know that there's anything we can do to prevent them.

The initialize thing is still a bug...so we're closer but not quite.


Stephen Bannasch - 19/Apr/07 10:03 PM
FYI: regarding the first two non-important error messages:

http://lists.apple.com/archives/Java-dev/2005/Jun/msg00546.html:

Subject: Re: Eclipse launches java app. with error: CFMessagePort bootstrap_register(): failed 1103

The message is a system diagnostic telling you that more than one process tried to register Services (i.e. the
"Services" submenu of your Application menu) with the process name "java". It should be harmless; if your
app is crashing, it's for some other reason.


Charles Oliver Nutter - 19/Apr/07 10:57 PM
Thanks Stephen...so I suppose it's a side effect of running multiple Java versions on the same system (since within a single version they should use the same in-memory HotSpot, but multiple versions wouldn't share HotSpots and would re-register...).

The remaining issues are scheduled to be fixed by Bill Dortch's uber-patch.


Charles Oliver Nutter - 20/Apr/07 12:06 AM
Bill's patch for JRUBY-814 will fix this bug.

Charles Oliver Nutter - 20/Apr/07 01:19 PM
This will be fixed when we commit the JRUBY-814 patch some time today.

Stephen Bannasch - 22/Apr/07 11:29 PM
FYI:

Just checked out r 3534. I still get:

helloswing.rb:9:in `initialize': invokee not a java object (TypeError)
        from helloswing.rb:9:in `new'
        from helloswing.rb:9

running this program:

require 'java'

class MyFrame < javax.swing.JFrame
  def initialize
    super("Hello Swing!")
    pack
  end
end

MyFrame.new.visible = true[~/dev/jr/sandbox/jruby]$

Charles Oliver Nutter - 23/Apr/07 12:18 AM
Still not fixed it seems...perhaps I should have double-checked that it was actually working...

Bill Dortch - 23/Apr/07 01:42 AM
This works on WinXP / Java 6 (on my desk). The problems seem to arise on Mac OS / Java 5. I've attached a diagnostic (jruby_778_diagnostic.rb, reproduced below) that may help shed some light on the problem. If folks could run it and report the results, I'd appreciate it.

Thanks, Bill

jruby_778.diagnostic.rb:

require 'java'

class MyFrame < javax.swing.JFrame
def initialize
  super
  puts "\nself = [#{self}]"
  puts "\nself.class = [#{self.class}]"
  if self.respond_to?(:java_class)
    puts "\nself.java_class = [#{self.java_class}]"
  else
    puts "\njava_class not defined"
  end
  if self.respond_to?(:java_object)
    puts "\nself.java_object = [#{self.java_object}]"
    puts "\njava_object JavaObject? = [#{self.java_object.kind_of?(Java::JavaObject)}]"
    puts "\njava_object.class = [#{self.java_object.class}]"
  else
    puts "\njava_object not defined"
  end
end
end
MyFrame.new.visible = true

Stephen Bannasch - 23/Apr/07 07:57 AM
Here's the output from jruby_778.diagnostic.rb Biill. I'm testing on:

jruby svn rev 3534
MacOS 10.4.9
$ java -version
java version "1.5.0_07"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-164)
Java HotSpot(TM) Client VM (build 1.5.0_07-87, mixed mode, sharing)

$ jruby jruby_778.diagnostic.rb
2007-04-23 08:52:19.981 java[3065] CFLog (0): CFMessagePort: bootstrap_register(): failed 1103 (0x44f), port = 0x18303, name = 'java.ServiceProvider'
See /usr/include/servers/bootstrap_defs.h for the error codes.
2007-04-23 08:52:19.982 java[3065] CFLog (99): CFMessagePortCreateLocal(): failed to name Mach port (java.ServiceProvider)
/Users/stephen/dev/jruby-trunk/jruby/src/builtin/javasupport.rb:128 warning: already initialized constant EXIT_ON_CLOSE

self = []

self.class = [MyFrame]

self.java_class = [javax.swing.JFrame]

self.java_object = []

java_object JavaObject? = [false]

java_object.class = [NilClass]


Bill Dortch - 23/Apr/07 09:01 AM
Stephen,

Thanks for the quick feedback. There was something in the output that suggested you might not be running the latest JRuby trunk version (the EXIT_ON_CLOSE warning should not be there, and javasupport.rb is now well under 100 lines). I've attached a version check script (reproduced below) – if you could run it and report the output, I'd really appreciate it.

BTW, this isn't to say that the bug isn't still there, I just want to make sure the symptoms are current.

Thanks,

Bill

jruby_version_check.rb

if defined?JRUBY_VERSION
  puts "JRUBY_VERSION = #{JRUBY_VERSION}"
else
  puts "JRUBY_VERSION not defined"
end
include Java
JFrame = javax.swing.JFrame
puts "JFrame ancestors:"
puts JFrame.ancestors.join("\n")

Stephen Bannasch - 23/Apr/07 10:02 AM
Hi Bill,

I think the error you noticed mentioning EXIT_ON_CLOSE is happening because Java and JRuby are registering for services more than once. See my comment 10 up from here.

Here are the results from running jruby_version_check.rb:

$ jruby jruby_version_check.rb
JRUBY_VERSION not defined
jruby_version_check.rb:6:in `const_missing': uninitialized constant Java (NameError)
        from jruby_version_check.rb:6

Here's more details from the shell:

This is how I setup my environment:

[~/dev/jr/sandbox/jruby]$ ./setpaths.sh 
[~/dev/jr/sandbox/jruby]$ cat setpaths.sh 
JRUBY_HOME=`pwd`
export JRUBY_HOME
PATH=`pwd`/bin:$PATH
export PATH

I got rev 3536 checked out:

$ svn info
Path: .
URL: svn://svn.codehaus.org/jruby/trunk/jruby
Repository Root: svn://svn.codehaus.org/jruby
Repository UUID: 961051c9-f516-0410-bf72-c9f7e237a7b7
Revision: 3536
Node Kind: directory
Schedule: normal
Last Changed Author: headius
Last Changed Rev: 3535
Last Changed Date: 2007-04-22 23:51:36 -0400 (Sun, 22 Apr 2007)

Just in case I'll compile it again.

[~/dev/jr/sandbox/jruby]$ ant
Buildfile: build.xml

init:

prepare:

compile.tasks:
     [copy] Copying 1 file to /Users/stephen/dev/jr/sandbox/jruby/build/classes/jruby

check-for-optional-java4-packages:

check-for-optional-packages:

compile-jruby:

compile:

serialize:

generate-method-classes:
    [touch] Creating /Users/stephen/dev/jr/sandbox/jruby/build/__empty.rb
   [delete] Deleting: /Users/stephen/dev/jr/sandbox/jruby/build/__empty.rb

jar-jruby:
      [jar] Building jar: /Users/stephen/dev/jr/sandbox/jruby/lib/jruby.jar

jar:

BUILD SUCCESSFUL
Total time: 19 seconds

And try running my test programs again:

[~/dev/jr/sandbox/jruby]$ jruby helloswing.rb
2007-04-23 10:51:56.006 java[3273] CFLog (0): CFMessagePort: bootstrap_register(): failed 1103 (0x44f), port = 0x18403, name = 'java.ServiceProvider'
See /usr/include/servers/bootstrap_defs.h for the error codes.
2007-04-23 10:51:56.007 java[3273] CFLog (99): CFMessagePortCreateLocal(): failed to name Mach port (java.ServiceProvider)
/Users/stephen/dev/jruby-trunk/jruby/src/builtin/javasupport.rb:128 warning: already initialized constant EXIT_ON_CLOSE
helloswing.rb:9:in `initialize': invokee not a java object (TypeError)
        from helloswing.rb:9:in `new'
        from helloswing.rb:9

[~/dev/jr/sandbox/jruby]$ jruby jruby_778.diagnostic.rb
2007-04-23 10:52:04.366 java[3276] CFLog (0): CFMessagePort: bootstrap_register(): failed 1103 (0x44f), port = 0x18103, name = 'java.ServiceProvider'
See /usr/include/servers/bootstrap_defs.h for the error codes.
2007-04-23 10:52:04.366 java[3276] CFLog (99): CFMessagePortCreateLocal(): failed to name Mach port (java.ServiceProvider)
/Users/stephen/dev/jruby-trunk/jruby/src/builtin/javasupport.rb:128 warning: already initialized constant EXIT_ON_CLOSE

self = []

self.class = [MyFrame]

self.java_class = [javax.swing.JFrame]

self.java_object = []

java_object JavaObject? = [false]

java_object.class = [NilClass]

[~/dev/jr/sandbox/jruby]$ jruby jruby_version_check.rb
JRUBY_VERSION not defined
jruby_version_check.rb:6:in `const_missing': uninitialized constant Java (NameError)
        from jruby_version_check.rb:6

Bill Dortch - 23/Apr/07 11:21 AM
Stephen,

Hmm, strange, I see that you're checking out the current version, but you're definitely not running against it. The JRUBY_VERSION constant has been in for about a week, since build 3478 (see http://fisheye.codehaus.org/changelog/jruby/?cs=3478), and "include Java" has been supported for much longer, I'd say at least a month.

While I don't see anything obviously wrong with your environment setup, I'm not really an expert on that sort of thing (even on Windows, which is my main platform). But I'd say you must have an older version of JRuby lying around somewhere, and somehow that's what is being run. Or maybe there's a build issue; have you tried "ant clean"?

If you have time to play around with this, it would be great to know what your results are with the current build. The output from jruby_version_check.rb should look like this:

JRUBY_VERSION = 0.9.9-pre
JFrame ancestors:
JFrame
Java::JAVA.AWT.Frame
Java::JAVA.AWT.Window
Java::JAVA.AWT.Container
Java::JAVA.AWT.Component
Java::JAVA.LANG.Object
ConcreteJavaProxy
JavaProxy
Object
Java
Kernel

If you wait for the 0.9.9 release later today, you may not see the JAVA.AWT... class names; I think they'll be disabled for the release. But you should at least see a list of classes between JFrame and ConcreteJavaProxy.

Thanks again for your feedback. Let me know what you find out.

-Bill


Stephen Bannasch - 23/Apr/07 01:21 PM
Hi Bill,

First – thanks very much for all your work and patience!

You are right. I was running an older jruby.

My problem was that I was executing my shell script by running it. Well that runs it in another shell so any of the parameters it sets are only valid until that shell exits – which is when my script finished (I should have known better).

The right way to execute this kind of script is with the 'source' command (also aliased as '.') like this:

$ source setpaths.sh

This executes the script in the context of the current shell. Now JRUBY_HOME and PATH are set correctly.

Would it make sense to log the JRUBY_VERSION and subversion revision to stderr? I wouldn't have wasted so much of your time.

The code now seems to work. Here are my results:

$ jruby helloswing.rb
2007-04-23 14:15:15.722 java[3524] CFLog (0): CFMessagePort: bootstrap_register(): failed 1103 (0x44f), port = 0x16603, name = 'java.ServiceProvider'
See /usr/include/servers/bootstrap_defs.h for the error codes.
2007-04-23 14:15:15.722 java[3524] CFLog (99): CFMessagePortCreateLocal(): failed to name Mach port (java.ServiceProvider)

except for the two (presumably harmless) in the console this roks fine.

Here's the output from the diagnostic:

[~/dev/jr/sandbox/jruby]$ jruby jruby_778.diagnostic.rb
2007-04-23 14:15:55.767 java[3526] CFLog (0): CFMessagePort: bootstrap_register(): failed 1103 (0x44f), port = 0x16903, name = 'java.ServiceProvider'
See /usr/include/servers/bootstrap_defs.h for the error codes.
2007-04-23 14:15:55.768 java[3526] CFLog (99): CFMessagePortCreateLocal(): failed to name Mach port (java.ServiceProvider)

self = [org.jruby.javasupport.proxy.gen.JFrame$Proxy0[frame0,0,22,0x0,invalid,hidden,layout=java.awt.BorderLayout,title=,resizable,normal,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,0x0,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=449,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]]

self.class = [MyFrame]

self.java_class = [javax.swing.JFrame]

self.java_object = [org.jruby.javasupport.proxy.gen.JFrame$Proxy0[frame0,0,22,0x0,invalid,hidden,layout=java.awt.BorderLayout,title=,resizable,normal,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,0x0,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=449,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]]

java_object JavaObject? = [true]

java_object.class = [Java::JavaObject]

And here's the output from the version check.

[~/dev/jr/sandbox/jruby]$ jruby jruby_version_check.rb
JRUBY_VERSION = 0.9.9-pre
2007-04-23 14:16:15.418 java[3528] CFLog (0): CFMessagePort: bootstrap_register(): failed 1103 (0x44f), port = 0x16703, name = 'java.ServiceProvider'
See /usr/include/servers/bootstrap_defs.h for the error codes.
2007-04-23 14:16:15.418 java[3528] CFLog (99): CFMessagePortCreateLocal(): failed to name Mach port (java.ServiceProvider)
JFrame ancestors:
Java::JAVAX::SWING::JFrame
Java::JAVA::AWT::Frame
Java::JAVA::AWT::Window
Java::JAVA::AWT::Container
Java::JAVA::AWT::Component
Java::JAVA::LANG::Object
ConcreteJavaProxy
JavaProxy
Object
Java
Kernel

Bill Dortch - 23/Apr/07 02:54 PM
Stephen,

Thanks for the follow up. I'm glad to see things are working for you now. I think we can mark this issue closed!

Cheers,

-Bill


Thomas E Enebo - 23/Apr/07 02:57 PM
The comments compel me to resolve this issue

Charles Oliver Nutter - 06/May/07 09:49 PM
Closing for 1.0RC1