Java Reflection: Determining class of java.util.regex.Pattern in JRuby

SRobertJames :

Working on a legacy JRuby app (1.6.8) running under Java 11, I traced a peculiar error a test case: "require 'java'; puts java::util::regex::Pattern.class" errors ArgumentError: wrong number of arguments (0 for 1). For other built-in JRE classes, this seems to work fine (see below).

This causes JRuby itself to fail sometimes, at this line in 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)

To get the app to work, I had to comment out that line in the JRuby source.

I'm perplexed as to the cause of this, or how to fix it appropriately. Google shows several instances of people getting that error when trying to load particular apps, but no one figuring out why (all the solutions said "try different versions of the app).

Why can JRuby not execute .class ? What argument is it expecting?

Complete trace below:

$ 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 behavior

Java itself seems to have no problem:

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

Partial Solution?

I can fix this error in JRuby by commenting out the if statement referenced above. However, on this legacy app, JRuby is in a compiled jar, and so I can't edit its source. Is there a way to add a monkey patch to JRuby, without changing the binary jar, to fix the failing if statement?

Getting JRuby

JRuby 1.6.8 is available at http://central.maven.org/maven2/org/jruby/jruby-dist/1.6.8/

GotoFinal :

I think that jruby is trying to read one of members of Pattern class:

private static int getClass(int c) {
    return sun.text.Normalizer.getCombiningClass(c);
}

as it looks a bit like getter but have that extra argument.

You can confirm that by creating own class like that:

class MyClass {
    private static int getClass(int c) {
        return 4;
    }
}

And then try to get class from it in JRuby.

It works with java 8 as this method was non-static, and like Holger said jruby seems to prefer to use existing static methods even if they do not match signature, and check for special ".class" property is done at the end. (As in java Something.class is not a property, but just a keyword)

Best option would be to have higher priority for methods that are matching invocation (0 needed arguments), and maybe for public methods. Also getters should probably only be matched by name of property only if they are really getters - so they do not have any arguments.

Download for this version of jruby does not work for me, so I can't test this: https://www.jruby.org/files/downloads/1.6.8/index.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=134569&siteId=1