Skip to content

Improve two-way integration of Java and Ruby exceptions #4781

@headius

Description

@headius

For #4699, we removed the automatic initCause call for Java exceptions raised from Ruby. There were a few issues with that logic:

  • Java does not automatically set cause for you, so there seemed to be a bit of a mismatch.
  • The cause can only be set once, so we must check if it has been set already. Attempting to set it again raises an illegal argument exception from Java.
  • The cause field is not volatile so you cannot check and set it safely across threads. It must be set under lock, and even then it is not guaranteed to be visible.
  • Cause was getting set on unrelated exceptions just because they got re-raised with $! in flight.

In light of these problems, I think we should not reinstate automatic cause-setting for Java exceptions, but we do need a way to provide a cause. There's a few ways this might be done...I try to describe some below.

RubyException could hold a reference to its "container" RaiseException, so it can be re-raised without making a new one.

When providing the Java cause, this exception could be used, either through a new JRuby-specific method:

ex.throwable
# or
ex.to_java(Throwable)

...or via some magic trickery during value conversion in JI, when we see a RubyException is being passed for a Throwable.

We have also discussed in the past building a parallel exception hierarchy for RaiseException. In this structure, all exception types that currently exist would still work, but for each Ruby exception there would be an equivalent Java exception of the same name. The two would be inseparable, like the proxy objects we use for JI. This would allow the Ruby exception to behave more naturally as a Java exception, and allow Java code to rescue Ruby exceptions by name (rather than the RaiseException dance we have today).

All this combined would improve our integration between Ruby and Java exceptions.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions