Call methods of a class generated in runtime
まだ誰も着手していません。
評価
調査の方向性
issue の InMemoryJavaCompiler の例で失敗を再現し、その後 JavaCall の core.jl で jcall 周辺と報告されている 244 行目および 373 行目から調べ始めてください。通常の dispatch と reflection ベースの jcall2 パスを比較してください。動的にコンパイルされたクラスのメソッドを jcall 経由で呼び出せ、継承されたメソッドも引き続き動作すれば完了です。
索引モデルが issue の本文から書いたものです。
説明
jcall fails with NoSuchMethodError when calling methods of a dynamically compiled class.
I use InMemoryJavaCompiler to compile a new class and create its instance. (InMemoryJavaCompiler is based on javax.tools.*, so quite standard approach).
const JInMemoryJavaCompiler = @jimport org.mdkt.compiler.InMemoryJavaCompiler
function mkclass(name::String, src::String)
jcompiler = jcall(JInMemoryJavaCompiler, "newInstance", JInMemoryJavaCompiler, ())
return jcall(jcompiler, "compile", JClass, (JString, JString), name, src)
end
function instantiate(name::String, src::String)
jclass = mkclass(name, src)
return jcall(jclass, "newInstance", JObject, ())
end
init()
name = "julia.compiled.Hello"
src = """
package julia.compiled;
public class Hello {
public String hello(String name) {
return "Hello, " + name;
}
public void goodbye() {
System.out.println("Goodbye!");
}
}
"""
obj = instantiate(name, src)
The resulting object looks like the ordinary one and I can see the methods I defined:
julia> listmethods(obj)
11-element Vector{JMethod}:
java.lang.String hello(java.lang.String)
void goodbye()
void wait(long)
void wait(long, int)
void wait()
boolean equals(java.lang.Object)
java.lang.String toString()
int hashCode()
java.lang.Class getClass()
void notify()
void notifyAll()
However, calling them with jcall fails, even though calling the inherited methods works fine:
julia> jcall(obj, "hello", JString, (JString,), "Bob")
Exception in thread "main" java.lang.NoSuchMethodError: hello
ERROR: JavaCall.JavaCallError("Error calling Java: java.lang.NoSuchMethodError: hello")
Stacktrace:
[1] geterror(allow::Bool)
@ JavaCall ~/.julia/packages/JavaCall/MlduK/src/core.jl:418
[2] jcall(obj::JObject, method::String, rettype::Type, argtypes::Tuple{DataType}, args::String)
@ JavaCall ~/.julia/packages/JavaCall/MlduK/src/core.jl:244
[3] top-level scope
@ REPL[13]:1
julia> jcall(obj, "goodbye", Nothing, ())
Exception in thread "main" java.lang.NoSuchMethodError: goodbye
ERROR: JavaCall.JavaCallError("Error calling Java: java.lang.NoSuchMethodError: goodbye")
Stacktrace:
[1] geterror(allow::Bool)
@ JavaCall ~/.julia/packages/JavaCall/MlduK/src/core.jl:418
[2] jcall(::JObject, ::String, ::Type, ::Tuple{})
@ JavaCall ~/.julia/packages/JavaCall/MlduK/src/core.jl:244
[3] top-level scope
@ REPL[14]:1
julia> jcall(obj, "equals", jboolean, (JObject,), obj)
0x01
What's even more confusing, these new methods can actually be called using the reflection:
function jcall2(jobj::JavaObject, name::String, ret_type, arg_types, args...)
jclass = getclass(jobj)
jargs = [a for a in convert.(arg_types, args)] # convert to Vector
meth = jcall(jclass, "getMethod", JMethod, (JString, Vector{JClass}), name, getclass.(jargs))
return meth(jobj, jargs...)
end
julia> jcall2(obj, "hello", JString, (JString,), "Bob")
"Hello, Bob"
julia> jcall2(obj, "goodbye", Nothing, ())
Goodbye!
Although it fails with NoSuchMethodException for the inherited method ¯_(ツ)_/¯:
julia> jcall2(obj, "equals", jboolean, (JObject,), obj)
Exception in thread "main" java.lang.NoSuchMethodException: julia.compiled.Hello.equals(julia.compiled.Hello)
at java.base/java.lang.Class.getMethod(Class.java:2108)
ERROR: JavaCall.JavaCallError("Error calling Java: java.lang.NoSuchMethodException: julia.compiled.Hello.equals(julia.compiled.Hello)")
Stacktrace:
[1] geterror(allow::Bool)
@ JavaCall ~/.julia/packages/JavaCall/MlduK/src/core.jl:418
[2] geterror
@ ~/.julia/packages/JavaCall/MlduK/src/core.jl:403 [inlined]
[3] _jcall(::JClass, ::Ptr{Nothing}, ::Ptr{Nothing}, ::Type, ::Tuple{DataType, DataType}, ::String, ::Vararg{Any})
@ JavaCall ~/.julia/packages/JavaCall/MlduK/src/core.jl:373
[4] jcall(::JClass, ::String, ::Type, ::Tuple{DataType, DataType}, ::String, ::Vararg{Any})
@ JavaCall ~/.julia/packages/JavaCall/MlduK/src/core.jl:245
[5] jcall2(jobj::JObject, name::String, ret_type::Type, arg_types::Tuple{DataType}, args::JObject)
@ Main ./REPL[17]:4
[6] top-level scope
@ REPL[18]:1
The code above is executable from the Spark#new-api branch, but honestly I hope that I'm just doing some stupid mistake that a keen eye can catch just from the description.
- 主要言語
- Julia
- スター
- 125
- フォーク
- 53
- PR マージ指標
- 30日以内にマージされた PR はありません
コントリビューションガイド
このリポジトリのコントリビューションガイドは索引されていません
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
JuliaInterop/JavaCall.jl のほかの issue
-
難易度 3/5 1〜2日 初心者へのやさしさ 45/100
JuliaInterop/JavaCall.jl#170 · コメント 5 件 ·
-
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
JuliaInterop/JavaCall.jl#169 ·
-
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
JuliaInterop/JavaCall.jl#156 · コメント 2 件 ·
-
難易度 4/5 3〜5日 初心者へのやさしさ 30/100
JuliaInterop/JavaCall.jl#150 · コメント 11 件 ·
-
難易度 5/5 1週間以上 初心者へのやさしさ 25/100
JuliaInterop/JavaCall.jl#145 · コメント 6 件 ·
JuliaInterop/JavaCall.jl の issue をすべて見る
似ている issue
-
tagbot-manual
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
-
documentation
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
Sienna-Platform/PowerSystems.jl#1800 ·
-
enhancement good first issue help wanted
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100