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

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

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

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

Q&A

解決済

2回答

570閲覧

呼び出しクラス名をすべて取得したい

takuson

総合スコア36

Java

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

0グッド

1クリップ

投稿2022/08/09 07:43

編集2022/08/22 11:31

前提

ClassAの処理の初めから終わりまでに呼ばれたクラス名を取得したいと思い、
Threadからクラス名を取得してみたところ、こちらの想定と違う結果となりました。
私が求めている結果は、ClassAでClassXとClassYを呼び出していたらその2つのクラスが表示されることです。
しかし、得られた結果はClassAのみでした。
最終的にやりたいことは、これを利用してjarや複雑に継承等を行ってる場合に使用しているクラスを明確化したいです。

実現したいこと

・ClassA最初から最後までの処理で呼び出されたクラス名(できればメソッド名)を取得したい
・結果を表示させる処理はClassAで行う

試したソースコード

Java

1package sample; 2 3public class ClassA { 4 public static void main (String[] args) { 5 ClassX.testMethod(); 6 ClassY.testMethod(); 7 printStackClass(); 8 } 9 10 private static void () { 11 int count = Thread.currentThread().getStackTrace().length - 1; 12 System.out.println("呼び出しクラスとメソッドを出力します"); 13 for (int i = count; i > 1; i--) { 14 System.out.println("クラス:" + Thread.currentThread().getStackTrace()[i].getClassName() 15 + ", メソッド:" + Thread.currentThread().getStackTrace()[i].getMethodName()); 16 } 17 } 18} 19

得られた結果

呼び出しクラスとメソッドを出力します クラス:ClassA, メソッド:main

求めている結果

呼び出しクラスとメソッドを出力します クラス:ClassA, メソッド:main クラス:ClassX, メソッド:testMethod クラス:ClassY, メソッド:testMethod

補足情報(FW/ツールのバージョンなど)

・eclipse 4.4
・Java 1.8
・Windows10

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

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

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

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

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

jimbe

2022/08/09 10:48 編集

当然ですが、スタックトレースにはスタックに積まれている情報しかありません。スタックは呼び出しの深さで積まれるもので、過去に実行したモノが残っているわけではありません。 プログラムの実行過程にどのようなクラス・メソッドを経由してきたかの情報が java システムのどこかにあるという話は聞いたことはありません。 そのような情報があるということはどこかから得られているのでしょうか。
maisumakun

2022/08/09 10:53

> ClassAの処理の初めから終わりまでに呼ばれたクラス名を取得したいと思い 何のために取得したいのでしょうか。
takuson

2022/08/09 14:02

>jimbeさん スタックトレースから呼ばれたクラス名が取得できるということは、それを設定しているところを見つけられれば使用しているすべてのクラス名を取得できると思ったからです。 ただ、いまいちその部分が見えなかったので質問しました。 >maisumakunさん 質問の内容ではやりたいことをわかりやすく説明するためにこのような書き方になりましたが、最終的にはjarなどで固められて、処理が追いにくい部分を見るためです。(前提に追記しました) ちなみにデバックなどはできないためこのような形となりました。
jimbe

2022/08/09 15:20

> スタックトレースから呼ばれたクラス名が取得できるということは、それを設定しているところを見つけられれば使用しているすべてのクラス名を取得できると思った いえ、先に書きました通り、スタックにはその瞬間のデータしか入っていません。「スタック」の基本的な動作をお分かりであれば過去の情報が残っているとは考えられないと思います。 ClassX の testMethod を呼んだ時にスタックには戻るための情報が入りますが、戻った段階でその情報は無効/破棄になり、ClassY の testMethod を呼んだ時に上書きされてしまって ClassX の testMethod が実行されていたことは残らないはずです。 また、そもそもそのような履歴情報が残るのであれば、ある程度システムが稼働し続けるとやがてメモリを食い潰すことになり、その為の何かしらの対応(オプションで一定時間毎にファイルに書き出すとか)が必要になるように思いますが、そのような話も聞いたことがありません。(ログツール等では必ずあると思います。) 以上から、スタックトレースからは無理では無いでしょうか。 java バイナリコードを解析して依存関係を再構築して表示するようなレベルのツールが必要な気がします。そして、そのようなツールは探したことも無いので分かりません。スイマセン。
takuson

2022/08/10 00:53

>jimbeさん ご解説頂いた通り、ClassXを呼び出した後にClassYを呼び出した時点でClassXを呼び出したことはスタックトレースからなくなることは理解しています。 なので、最終的なスタックトレースからクラス名を取得するつもりはありません。(上記のソースコードのせいで混乱させてしまったのであればすみません) 今考えていることとしては、スタックトレースにスラス名を設定しているメソッドを探し、そのメソッドをオーバライドし、別途クラス名を格納するリストを用意する。 その後そのリストを直接表示させるか、ファイル出力するかは後々考えればいいと思っています。
jimbe

2022/08/10 03:16

スタックトレースにクラス名を設定しているメソッド・・・というものも無いのではないでしょうか。 スタックトレースのスタックは、アプリやライブラリレベルからは透過的に存在するものです。 java エンジン自体のコード ( は java では無いでしょう ) を見ればどこかしらにはスタックに入れている処理はあるはずですが、 java アプリから上書き出来るようなレベルでは無いはずです。 一時期良く聞いたアスペクト指向の紹介例として「既存のコードにログを仕込むのが簡単」というようなモノをよく見かけたように思います。 takuson さんの現状で使えるものか、機能として希望に添えるものか分かりませんが、 java にも AspectJ とかなんとかがあったと思いますので、そのような方向もご検討されては如何でしょうか。
guest

回答2

0

解決方法というか結論
・Threadクラスのスタックトレースを利用した方法では実現不可能
・スタックトレースを設定している個所もJavaソース内に存在しないためそこからの取得も不可能

以上のことから実現する場合は、AspectJやログを各クラスごとに仕込むしかない

投稿2022/08/10 06:17

takuson

総合スコア36

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

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

0

ベストアンサー

@takuson

れば使用しているすべてのクラス名を取得できると思ったからです。

使用しているすべてのクラス名を取得したい。であれば、java -verbose:classでいいのでわ。

java

1public class Hello { 2 public static void main(String[] args) throws Exception { 3 System.out.println("hello"); 4 System.out.println(new java.util.ArrayList()); 5 } 6}
$ javac Hello.java $ java -verbose:class Hello [0.334s][info][class,load] java.lang.Object source: shared objects file [0.339s][info][class,load] java.io.Serializable source: shared objects file [0.339s][info][class,load] java.lang.Comparable source: shared objects file ... [0.409s][info][class,load] java.security.UnresolvedPermission source: shared objects file [0.409s][info][class,load] java.security.SecureClassLoader$DebugHolder source: shared objects file [0.409s][info][class,load] sun.security.util.Debug source: shared objects file [0.410s][info][class,load] Hello source: file:./ [0.410s][info][class,load] java.lang.NamedPackage source: shared objects file [0.410s][info][class,load] java.lang.PublicMethods$MethodList source: shared objects file [0.410s][info][class,load] java.lang.PublicMethods$Key source: shared objects file [0.410s][info][class,load] java.lang.Void source: shared objects file hello [0.411s][info][class,load] java.util.ArrayList$Itr source: shared objects file [] [0.411s][info][class,load] java.lang.Shutdown source: shared objects file [0.411s][info][class,load] java.lang.Shutdown$Lock source: shared objects file

投稿2022/08/10 05:58

shiketa

総合スコア3971

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

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

takuson

2022/08/10 06:49

回答ありがとうございます。 結果として求めているものはこれで大丈夫なのですが、対象のクラスを実行する際に上記ですとコマンド実行のようなので、これをEclipseからすることは可能でしょうか?
shiketa

2022/08/10 07:44

Eclipseは詳しくありませんが、実行時オプションを設定できるのではないですか?
takuson

2022/08/22 02:31

返信が遅くなりすみません Eclipseの設定については軽く確認してみたのですが、該当する箇所は見つかりませんでした... ただ本件とはまた別問題なのかなと思うので、一旦こちらの内容をベストアンサーとさせていただきます ご回答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問