Fork me on GitHub
#graalvm
<
2021-09-26
>
quoll03:09:10

I need to extend a Java class, and I’ve been using proxy to do this. This compiles to native, but then using the object gives me “No matching field found” for the function that I’ve overridden. I’m thinking that using proxy may not be allowed when compiling to native, since it’s dynamically creating the class at runtime. Is that right? If so, then I’m thinking that the best approach is to use gen-class to create this class statically. Or am I missing something that’s easier?

Karol Wójcik06:09:06

I hope not. Do you have warn-on-reflection true?

Karol Wójcik07:09:56

Proxy should work since it creates a class file on macroexpansion

ericdallo14:09:02

I think it should work if you can declare the resulting generated class in the reflection config

ericdallo14:09:21

Also, there is the proxy config on graalvm, for lsp4j on clojure-lsp I needed to declare these classes on proxy config. Ref: https://github.com/clojure-lsp/clojure-lsp/blob/master/resources/META-INF/native-image/clojure-lsp/clojure-lsp/proxy-config.json#L2

quoll01:09:08

Figured it out!

quoll01:09:30

I wasn’t hinting appropriately and it was reflecting to call the method

quoll01:09:06

As for proxy, it appears that calling proxy-super will try to call the method on the superclass, but it attempts to reflect to find it

quoll01:09:37

There’s no way to type-hint in a proxy, so I can’t avoid the reflection

quoll01:09:36

What I’m trying to do is to create a PushbackReader that returns a 0 when it encounters a ; character.

quoll01:09:51

This works when it’s run in the JVM:

(proxy [PushbackReader] [reader-input]
  (read [] (let [c (proxy-super read)]
             (if (= (int \;) c)
               0
               c))))

quoll01:09:31

But when compiled, then the call to proxy-super tries to reflect

quoll01:09:20

Instead, I did it with this:

(gen-class
  :name "asami.PBR"
  :extends java.io.PushbackReader
  :prefix "pbr-"
  :exposes-methods {read readSuper})

(defn pbr-read
  [this]
  (let [c (.readSuper ^asami.PBR this)]
    (if (= (int \;) c)
      0
      c)))
Then, instead of returning a proxy, I just instantiated it:
(asami.PBR. reader-input)

quoll01:09:05

The type hint for this when calling .readSuper is what fixed it

quoll01:09:33

It’s obvious now, but at 1am my head had stopped working entirely 🙂

ericdallo12:09:06

Oh that makes sense, good catch :)