質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

2回答

5189閲覧

Java リフレクション フィールドが見つからないエラー

katliner

総合スコア13

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2018/02/27 13:32

編集2018/03/09 01:54

前提・実現したいこと

MinecraftというゲームのMODを作っているのですが、そのMODから更に外部のJarファイルを読み込むというものを作っています。
プログラムが実行されると、外部のJarを読み込み、さらにその中のプログラムをリフレクションを使用し、実行させるというものです。

arという変数が見つからないという問題が起きています。

関係は次のようになっています。
Minecraft
リフレクションを使用して外部JarのMODを実行
私の作っているMODの関数が呼ばれる
更にリフレクションを使用して外部のJarを実行(invoke)
そこでクラスは見つかるが変数が見つからないというエラーが出る

invokeしたプログラムでは変数を書き換えることはありません。

発生している問題・エラーメッセージ

arという変数が見つからないエラーが出てしまいます。

java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at versionsmod.versionsmod.init(versionsmod.java:57) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at cpw.mods.fml.common.FMLModContainer.handleModStateEvent(FMLModContainer.java:532) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) at com.google.common.eventbus.EventBus.post(EventBus.java:275) at cpw.mods.fml.common.LoadController.sendEventToModContainer(LoadController.java:212) at cpw.mods.fml.common.LoadController.propogateStateMessage(LoadController.java:190) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) at com.google.common.eventbus.EventBus.post(EventBus.java:275) at cpw.mods.fml.common.LoadController.distributeStateMessage(LoadController.java:119) at cpw.mods.fml.common.Loader.initializeMods(Loader.java:737) at cpw.mods.fml.client.FMLClientHandler.finishMinecraftLoading(FMLClientHandler.java:311) at net.minecraft.client.Minecraft.startGame(Minecraft.java:597) at net.minecraft.client.Minecraft.run(Minecraft.java:942) at net.minecraft.client.main.Main.main(Main.java:164) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) at net.minecraft.launchwrapper.Launch.main(Launch.java:28) at net.minecraftforge.gradle.GradleStartCommon.launch(Unknown Source) at GradleStart.main(Unknown Source) Caused by: java.lang.NoSuchFieldError: ar at test.test.init(test.java:21) ... 44 more

test.javaというのは外部Jarの.classのファイルのことです。

該当のソースコード

versionsmod.java

Java

1/*38行目*/@EventHandler 2public void init(FMLInitializationEvent e) { 3 File modDir = new File(mod_dir); 4 System.out.println(Block.class); 5 try { 6 for(String className : loadedClasses) { 7 if (className.toLowerCase().substring(className.toLowerCase().lastIndexOf(".")).equals(".class")) { 8 System.out.println("load "+className.replace("/", ".").replace(".class", "")); 9 Class clas = getClass().getClassLoader().loadClass(className.replace("/", ".").replace(".class", "")); 10 if(clas.getAnnotation(Mod.class) != null) { 11 Mod m = (Mod) clas.getAnnotation(Mod.class); 12 Object o = clas.newInstance(); 13 mods.put(m, o); 14 for(Method meth : clas.getDeclaredMethods()) { 15 Class[] classes = meth.getParameterTypes(); 16 if(classes.length==1&&classes[0].getName().equals(FMLInitializationEvent.class.getName())) { 17 try { 18 meth.setAccessible(true); 19 FMLInitializationEvent event = new FMLInitializationEvent(); 20 meth.invoke(o, event); 21 }catch(InvocationTargetException e11) { 22 e11.printStackTrace(); 23 } 24 } 25 } 26 } 27 } 28 } 29 } catch (Exception e1) { 30 e1.printStackTrace(); 31 } 32}

test.java(外部Jarの中に入っているtest.class)

Java

1/*19行目*/@EventHandler 2public void init(FMLInitializationEvent e) { 3 System.out.println(Item.ar); 4}

試したこと

外部Jarの中に以下のソースを書き、実行しました。

Java

1for(Field field : Item.class.getFields()) { 2 System.out.println(field.getName()); 3}

するとarというフィールドが存在するというのがわかりました。
しかしinvokeでは見つからないというのがよくわかりません。

補足情報

Minecraft Forge 1.7.10-10.13.4.1558
Eclipse 4.4
Windows 10 64bit

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/02/27 15:55

エラーは勝手な意訳じゃなく原文を乗せましょう。
guest

回答2

0

とりあえずあなたの基本的な知識が不足しすぎてるのでリフレクションの使用は早いと思います。

たとえば

if(classes.length==1) if(classes[0].getName().equals(FMLInitializationEvent.class.getName())) {

if(classes.length==1 && classes[0].getName().equals(FMLInitializationEvent.class.getName())) {

ですし

使いたいクラスのメソッドがわかってる場合は

clas.getDeclaredMethods()

で全部とって 引数チェックだけでつかうんじゃなく

clas.getDeclaredMethod("targetMethodName", FMLInitializationEvent.class)

と完全にしぼって取得すべきですしいろいろとだめだめだな・・・

投稿2018/03/08 14:40

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

katliner

2018/03/08 14:44

最後のメソッド名ですが メソッド名は決まっておらず、特定の引数が指定されていればそれを実行するというものになっています。 MinecraftのMODがそういう仕組ですので... 実際にソースコードを解析してみましたが複雑で、しかもそのメソッドをどこから呼び出しているかもわからなかったので自分なりに作ってみました。 if(...&&...)の方は全部実行されるのかと思ってたので分けてました。
退会済みユーザー

退会済みユーザー

2018/03/08 15:00

他にも、コメントついてる発生場所は少なくとも20行以上の場所ですよね? 読込の発生個所は17行目ですよ
退会済みユーザー

退会済みユーザー

2018/03/09 01:46

提示された実行クラスの行数とエラーログの行数が一致してないな at java.lang.reflect.Method.invoke(Method.java:498) at versionsmod.versionsmod.init(versionsmod.java:73) : File modDir = new File(mod_dir);
guest

0

【1】

どうしたら変数を見つけることができますか?

を実行すると、arが存在することが確認できました。

が相反している記述のように受け取れますが、ar変数は存在することが確認できた=見つけられたということで、この問題は解決しているのですか?

【2】

関数はしっかりpublic staticとしています。

質問文にそれがかかれていないので意味がわからないですし、そもそもメソッドをstaticにするのとリフレクションを使うことが何らかの相互作用をもたらすわけではないのでわざわざ記載した意図はなんでしょうか?

【3】
質問文からは何がしたいのか意図が汲み取れませんでしたが、想像しまして、ar変数に何らかの値をセットしたいのだとすれば、ar変数はprivate変数の可能性が高いのでfield.setAccesible(true);をしてから操作してみてはいかがでしょうか。
もしやりたいことが別であれば、具体的に何をしたいか書いてくれないとわからないですよ。

投稿2018/03/08 13:57

yukapome789

総合スコア361

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

katliner

2018/03/08 14:06

【1】は、getFields()だとしっかりとあるのにinvokeだと見つからないという意味です。 【2】は、public staticであることが重要かと思ったので書きました。 【3】ですが値を書き換えたいということではなく値を使いたいです。 注意されたところを編集しておきました。わかりにくくて本当にすみません...
退会済みユーザー

退会済みユーザー

2018/03/08 14:18

しかし質問者のひどいな getFields() で ar あったよ(多分引数個数ちがうやつ public) getDeclaredMethods() で このクラスが引数で渡せる適当なメソッドを実行してください
yukapome789

2018/03/08 14:46

>kusaankoさん 編集対応ありがとうございます。あとは、質問文に見出しを付けると、回答者の人に優しいと思いますよ。今の状態だと上から一字一句読まないと何言ってるのかわからないので。。 asahina1979さんの言ってる内容でできると思うので頑張って下さい
katliner

2018/03/08 14:51

>kadさん ありがとうございます。 明日頑張ってみようかと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問