Отражение Java: Определение класса java.util.regex.Pattern в JRuby - PullRequest
0 голосов
/ 07 января 2019

Работая над устаревшим приложением 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 Ответ

0 голосов
/ 09 января 2019

Я думаю , что 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" выполняется в конец. (Как в java Something.class это не свойство, а просто ключевое слово)

Наилучшим вариантом будет иметь более высокий приоритет для методов, которые соответствуют вызову (0 необходимых аргументов), и, возможно, для открытых методов. Кроме того, геттеры, вероятно, должны совпадать только по имени свойства, только если они действительно являются геттерами, поэтому у них нет аргументов.

Загрузка для этой версии jruby не работает для меня, поэтому я не могу проверить это: https://www.jruby.org/files/downloads/1.6.8/index.html

...