Отражение Java: Определение класса java.util.regex.Pattern в JRuby
Работая с устаревшим приложением JRuby (1.6.8), работающим под Java 11, я обнаружил странную ошибку в тестовом примере: "require 'java'; puts java::util::regex::Pattern.class"
ошибки ArgumentError: wrong number of arguments (0 for 1)
, Для других встроенных классов JRE это работает нормально (см. Ниже).
Это иногда приводит к сбою самой JRuby, в этой строке в https://github.com/jruby/jruby/blob/1.6.8/lib/ruby/site_ruby/shared/builtin/javasupport/core_ext/object.rb#L10:
if self.class.superclass.instance_method(:method_added) != method(:java_package_method_added)
Чтобы приложение работало, мне пришлось закомментировать эту строку в источнике JRuby.
Я озадачен относительно причины этого, или как исправить это соответствующим образом. Google показывает несколько случаев, когда люди получали эту ошибку при попытке загрузить определенные приложения, но никто не мог понять, почему (все решения сказали "попробуйте разные версии приложения).
Почему JRuby не может выполнить .class
? Какой аргумент он ожидает?
Заполните след ниже:
$ java -version
java version "11.0.1" 2018-10-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.1+13-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.1+13-LTS, mixed mode)
$ ./jruby -v
jruby 1.6.8 (ruby-1.8.7-p357) (2012-09-18 1772b40) (Java HotSpot(TM) 64-Bit Server VM 11.0.1) [linux-amd64-java]
$ ./jruby -e "require 'java'; puts java::util::regex::Matcher.class"
WARNING: An illegal reflective access operation has occurred
...
Class
$ ./jruby -e "require 'java'; puts java::lang::String.class"
WARNING: An illegal reflective access operation has occurred
...
Class
$ ./jruby -e "require 'java'; puts java::util::regex::Pattern.class"
WARNING: An illegal reflective access operation has occurred
....
ArgumentError: wrong number of arguments (0 for 1)
(root) at -e:1
Поведение Java
Сама Java, похоже, не имеет проблем:
jshell> int.class
$6 ==> int
jshell> String.class
$7 ==> class java.lang.String
jshell> Pattern.class
$8 ==> class java.util.regex.Pattern
jshell> Pattern.class.getClass()
$12 ==> class java.lang.Class
jshell> String.class.getClass()
$13 ==> class java.lang.Class
Частичное решение?
Я могу исправить эту ошибку в JRuby, закомментировав if
заявление, указанное выше. Однако в этом унаследованном приложении JRuby находится в скомпилированном фляге, и поэтому я не могу редактировать его исходный код. Есть ли способ добавить патч обезьяны в JRuby, не изменяя бинарный jar, чтобы исправить сбой if
заявление?
Получение JRuby
JRuby 1.6.8 доступен по адресу http://central.maven.org/maven2/org/jruby/jruby-dist/1.6.8/
1 ответ
Я думаю, что jruby пытается прочитать одного из членов класса Pattern:
private static int getClass(int c) {
return sun.text.Normalizer.getCombiningClass(c);
}
как это выглядит немного как получатель, но есть этот дополнительный аргумент.
Вы можете подтвердить это, создав собственный класс следующим образом:
class MyClass {
private static int getClass(int c) {
return 4;
}
}
А потом попробуйте получить класс от него в JRuby.
Он работает с java 8, так как этот метод был нестатичным, и, как сказал Хольгер, jruby, похоже, предпочитает использовать существующие статические методы, даже если они не соответствуют сигнатуре, и проверка на наличие специального свойства ".class" выполняется в конце. (Как в яве Something.class
это не свойство, а просто ключевое слово)
Лучшим вариантом будет иметь более высокий приоритет для методов, которые соответствуют вызову (0 необходимых аргументов), и, возможно, для открытых методов. Кроме того, геттеры, вероятно, должны совпадать только по имени свойства, только если они действительно являются геттерами, поэтому у них нет аргументов.
Загрузка для этой версии jruby не работает для меня, поэтому я не могу проверить это: https://www.jruby.org/files/downloads/1.6.8/index.html