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

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

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

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

Q&A

1回答

7513閲覧

システムクラスローダを取得する処理について

domingojapan

総合スコア26

Java

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

0グッド

0クリップ

投稿2017/04/24 09:56

###前提
Windowsでのみ動作保証しているアプリとなります。

###該当のソースコード

Java

1//システムクラスローダを取得する処理 2URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();

###発生している問題・エラーメッセージ
Java8を使用しているPCでは正常に稼働します。
Java9(Early-Accessですが...)だと上記ソースコードに対してExceptionが吐き出されました。

Exception in thread "main" java.lang.ClassCastException: java.base/jdk.internal.loader.ClassLoaders$AppClassLoader cannot be cast to java.base/java.net.URLClassLoader

###実現したいこと
アプリユーザはJava8/9のいずれかを使用しているので、両方に対応できるように修正したいです。

Java9のみExceptionを吐いた理由として、
「Java9の仕様として"AppClassLoader"が"URLClassLoader"を継承しなくなった」
が原因だと考えています。
適切な回避方法に関して知己がある方、アドバイスをお願いします。

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

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

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

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

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

guest

回答1

0

URLClassLoaderではなく型をClassLoaderとして宣言すればよいと思います。
JDK8限定だとしてもそうすべきではないでしょうか?

原因がおわかりのような気がするのですがURLClassLoaderとしなければならない理由があればそれを明記されたほうがよいと思います。


追記:コメントを拝見して感じたことを整理します。

コメントを拝見すると、URLClassLoaderを仮定したい動機がURLClassLoader#addURLを使うことのようです。それをするということはJVM起動時にクラスパスへ存在していなかったパスを「あたかも初めからクラスパスへ指定していたかのように追加したい」ということのように思えました。

そこが自分には疑問でした。JVM起動時にクラスパスへ必要なパスを指定すれば済むように思えるのですが、なぜ起動後に動的に追加するという面倒な方法を使う必要があるのかがわかりません。例えばサーバープログラムのようなものだとJVMを停止しないままで動的にコンフィギュレーションを切り替えるといったことが必要な場面があるのかも知れないと想像しますが、JVMを停止させないということは稼働中のサービスを止めたくないという意図があるのだとして、プログラムを動かしたままクラスパスを動的に変更するということが安全にできるものだろうかという疑問がわいてくるのです。

サーバーに関しては自分に経験が乏しいために「ほしい場面」を想定することができないだけなのかも知れませんが・・・

投稿2017/04/24 10:04

編集2017/06/14 12:32
KSwordOfHaste

総合スコア18394

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

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

domingojapan

2017/04/24 13:00

冷静に考えるとそうですね。。。。。 Exception吐いた時は、いかにして無理矢理URLClassLoaderにキャストする事しか考えてなかったです。 ごもっともな指摘ありがとうございました。
domingojapan

2017/06/14 02:17 編集

java9の正式リリースがまだなので実装を放置していましたが、 ようやく修正検討に着手しました。 >原因がおわかりのような気がするのですがURLClassLoaderとしなければならない理由があればそれを明記されたほうがよいと思います。 スレッド投稿時のExceptionが発生する部分のソース URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader(); に続くソースが Class<URLClassLoader> systemclass = URLClassLoader.class; try { Method method = systemclass.getDeclaredMethod("addURL", new Class[] {URL.class}); method.setAccessible(true); method.invoke(sysloader, new Object[] {modelJarFile.toURI().toURL()}); } catchは省略 となっていました。このなかの "addURL"がURLClassLoaderのprotectedのメソッドになります。 恐らくClassLoader型で宣言だと使えない気がします。 (初投稿時にソースをここまで書くべきでした。すいません) Exceptionを回避するための良い回避策はないでしょうか?
KSwordOfHaste

2017/06/14 02:46

やはり、「なぜそのようなことが必要なのか」を明示するほうがよいと思います。システムクラスロードーに修正を加えるよりはCLASSPATH環境変数やjava起動パラメーターへの-cpの指定やMANIFESTファイル内へのクラスパスの指定などいくつかの標準的な方法があると思います。そのような標準的な方法を使わずにシステムクラスローダーを「変更する」ことは自然な方法ではない気がします。よって「なぜそれをしなければならないのか」を示すことで根本的な解決方法を考えることができると思います。
domingojapan

2017/06/14 12:11

>「なぜそのようなことが必要なのか」を明示するほうがよいと思います 議題に取り上げた上記ソースは前任者からの引継いだものとなります。 正直な所、システムクラスローダ周りの仕様対して理解が不足している状態です。 KSowrdさんの返信を拝見するまで、「システムクラスローダを変更する」方法でしか 今回のExceptionは回避できないと思っていました... 「MANIFESTファイル内へのクラスパスの指定」となると URL.classの指定を追加するで合っていますか? ・
KSwordOfHaste

2017/06/14 12:32

自分の感じたことを一旦整理して回答へ追記いたしました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問