-
-
Notifications
You must be signed in to change notification settings - Fork 925
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JDK8 provides its own List#sort, Map#replace, and Map#merge #1249
Comments
This is going to be troublesome to fix. The problem is that our sort impl lives on the interface proxy for List, but when we bind methods from Java into concrete classes, we always bind the concrete versions. (For reasons I won't go into, we can't have the actual interface methods present on the interface proxy.) This means that even though we define a zero-argument #sort on our List proxy, the one-argument sort on ArrayList (or LinkedList, or any other list) is the one seen by Ruby dispatch. There's no trivial way around this. One way might be to enlist a form of the old lazy extender logic we used to have for decorating classes without loading them. We'd have an extender associated with List that would be applied to subclasses when they load. However, the unfortunate side effect, even if we can get our version of sort to be visible on ArrayList, is that the original version will then be masked away. We may have to end up saying this is a Java 8 "feature" we can't do anything about, since our interface patching can't trump concrete methods. |
Expanding this bug to encompass a few other methods I had to patch around in 8783a11:
These breakages are unfortunate, but so far theres not many. |
stumbled up this problem with A possible workaround is to reopen the concrete Map classes and redefine the if ENV_JAVA['java.specification.version'] >= '1.8'
class Java::JavaUtil::HashMap
def merge(other)
dup.merge!(other)
end
end
end |
Needed to use the @colinsurprenant workaround for https://github.com/mdedetrich/java-premailer-wrapper and can confirm that for my case it at least works |
was thinking about a support solution for users running into these while doing #3802 ... if all methods are native its pretty easy for JRuby to setup different names that would not conflict. users would than alias those when a ruby_ version is preferred in Ruby land e.g. : java.util.ArrayList.class_eval { alias_method :sort, :ruby_sort }
java.util.HashMap.class_eval { alias merge, ruby_merge; alias replace ruby_replace } needs to be done for every List/Map impl but that should be understandable, if its too much of an annoyance we can push it further ... also, not really a Java 8 conflict but still confusing : jruby-1.7.24 :001 > java.util.ArrayList.new.first
=> nil
jruby-1.7.24 :002 > java.util.LinkedList.new.first
Java::JavaUtil::NoSuchElementException:
from java.util.LinkedList.getFirst(java/util/LinkedList.java:244)
from java.lang.reflect.Method.invoke(java/lang/reflect/Method.java:498)
from RUBY.evaluate((irb):2) ... feels like |
…ava.util.Map users will be able to do use ruby versions with a simple alias on concrete types e.g. `java.util.HashMap.class_eval { alias merge ruby_merge }` resolves jruby#1249
We have been providing monkey-patched List#sort, Map#replace, and Map#merge, but they now conflict with the ones from JDK8. For example, sort:
public void sort(Comparator<? super E> c)
We add a sort to list that just turns a passed block into a Comparator. Because Ruby does not do overloads, only the one-argument version in ArrayList is seen, which causes our tests to fail like so:
The text was updated successfully, but these errors were encountered: