Javaのクラスパスは、どこで確認できるの?

f:id:ts0818:20201206133209j:plain

itigotofu.hatenablog.com

「悲しいときー!」「悲しいときー!」

「夕日が沈んだときぃ!」

https://itigotofu.hatenablog.com/entry/2019/02/20/000000

⇧ 皆々様、ご存知、お笑いコンビ「いつもここから」のネタですね、どうもボクです。

確かに、夕日が沈んでいく様子は「もの悲し」気分になりがちですが、「TOMMOROW(岡本真夜)」で「涙の数だけ強くなれるよ」って歌詞がありますが、「涙」と言えば、

yumenavi.info

 19世紀末、ウィリアム・ジェームズとカール・ランゲという心理学者が提唱した「ジェームズ・ランゲ説」に、「悲しいから泣くのではない、泣くから悲しいのだ」という有名なフレーズがあります。彼らによると、涙という生理反応が生じた後、その反応に対する一種の解釈として悲しくなるというのです。ジェームズ・ランゲ説が感情のすべてを説明できるわけではありませんが、触覚によって生理反応を演出することで、心の動きをある程度操作できることはわかっています。

夢ナビ 大学教授がキミを学問の世界へナビゲート

⇧「ジェームズ・ランゲ説」は有名ですが、

この説の反対を主張するのが「キャノンバード説」というものらしい。

脳中枢で生じるプロセスが抹消反応に先行するとする。ジェームズ=ランゲ説に対して、「悲しいから泣く」と説明される。

https://cp-info.net/archives/149

 

「鶏が先か、卵が先か」じゃないけども、「身体反応が先か、感情反応が先か」ってことが議論されてきたそうな。

「泣くから悲しい」「悲しいから泣く」確かに、どっちが本来の挙動なんでしょうね?

ただ、「エレファントカシマシ」の「宮本浩次」さんの「冬の花」の歌詞で、

www.youtube.com

悲しくって泣いてるわけじゃあない 生きてるから涙が出るの

https://www.youtube.com/watch?v=iQhRmQWwDYs

⇧「生きてるから涙が出るの」って言葉が出てくるんですが、衝撃ですね...

「悲しいから泣いてるんじゃない」んだと、「生きてる」から「涙」が出るんだと。

確かに、「涙」は様々な要因で起こる現象でしょうけど、「生きてる」からこそですからね、だって「嬉し涙」って言葉もあるぐらいだし、「涙」が出るのは「悲しい」時だけじゃないんよね。

冬の花」良い歌ですね。

というわけで、今回は、Javaです。レッツトライ~。

 

クラスパスって?

Javaのクラスパスが本当、分かり辛いんだわ...

どうにかならんもんかね?っていうぼやきつつ、確認して参りましょう。

Oracleさんによりますと、 

docs.oracle.com

クラスパスは、Java 実行環境がクラスおよび他のソースファイルを検索するパスです。

https://docs.oracle.com/javase/jp/1.5.0/tooldocs/windows/classpath.html

⇧ ってな感じで、「ファイル」を「検索するパス」ってことですが、

クラス検索パス (「クラスパス」という短い名前が一般的) の設定は、JDK ツールを呼び出すときに -classpath オプションを付ける方法 (推奨される方法) か、CLASSPATH 環境変数を設定する方法により行います。-classpath オプションが推奨されているのは、アプリケーションごとに個別に設定できるので、ほかのアプリケーションに影響を与えたり、ほかのアプリケーションからこの値が変更されたりすることがないためです

https://docs.oracle.com/javase/jp/1.5.0/tooldocs/windows/classpath.html

⇧「クラス検索パス」 には、

 の2つの方法があるらしい。

JDK ツールを呼び出すときに -classpath オプションを付ける方法 (推奨される方法)

sdkTool -classpath classpath1;classpath2...    

CLASSPATH 環境変数を設定する方法

set CLASSPATH=classpath1;classpath2...    

ってことみたいですと。

sdkTool

コマンド行ツール (javajavacjavadocapt など) です。JDK ツールのリストは、「JDK ツールとユーティリティ」 を参照してください。

https://docs.oracle.com/javase/jp/1.5.0/tooldocs/windows/classpath.html

classpath1;classpath2

.jar、.zip、または .class ファイルへのクラスパスです。各 classpath の末尾は、ファイル名かディレクトリのどちらかです。これは、クラスパスに何を設定するかによって異なります。

  • .jar または .zip ファイル (.class ファイルを含む) の場合、クラスパスは .zip または .jar ファイルの名前で終わる
  • 名前のないパッケージ内の .class ファイルの場合、クラスパスは .class ファイルを含むディレクトリの名前で終わる
  • 名前付きのパッケージ内の .class ファイルの場合、クラスパスはルートパッケージ (完全指定のパッケージ名の先頭パッケージ) の入ったディレクトリの名前で終わる

複数のパスエントリがある場合は、セミコロンで区切ります。set コマンドでは、等号 (=) の前後に空白を入れないように注意してください。

https://docs.oracle.com/javase/jp/1.5.0/tooldocs/windows/classpath.html

⇧ まぁ、いろいろ注意事項があったり、Java実行環境にとっての「クラス検索パス」ってものの設定方法は分かったんだけども、その設定された「クラスパス」を我々人間が検索したい場合はどこで確認すれば良いのかね?と思ってしまうんだけどね。

だって、「クラスパス」を設定した人しか分からないってことだと、開発現場で属人化するってことだものね。

いま、どんな「クラスパス」が設定されてるのか調べる方法が無いと辛いよね?

ちなみに、

CLASSPATH 環境変数がシステムの起動時に設定されている場合、その設定場所はオペレーティングシステムによって異なります。

https://docs.oracle.com/javase/jp/1.5.0/tooldocs/windows/classpath.html

⇧ ってな感じで、「環境変数」の「CLASSPATH」の設定がややこしそうね...

設定周りでバリバリにOS依存するんだね...

ってツッコミどころ満載なんだけど、「JavaのアプリケーションはJVM上で動作するなら、OSへの依存はほぼない」って聞いてきたけど、「ただし、JVM起動前の設定はOSに依存することがあり得る」ってことになるんですかね?

 

クラスパスってどこで確認できるの?

ということで、 「クラスパス」ですが、どこに設定されてるのかは、プロジェクトの環境によって異なると思われるので、プロジェクトの匙加減次第ってことですかね...

つまり、属人化する可能性は大いにあり得るってことザマスかね~...

ただ、開発でEclipse を使ってる場合は、

confrage.jp

⇧上記サイト様によりますと、「パースペクティブ」で「デバッグ」を選択して、「ビュー」の「デバッグ」に表示される「javaw.exe」上で右クリックして「プロパティ」を選択すれば確認できるらしい。(本番環境にデプロイされたら、全く異なる「クラスパス」になるんだとは思われますが...)

ただ、「デバッグ」を実行してないと「javaw.exe」は表示されないっぽいですかね。

f:id:ts0818:20201205163615p:plain

パースペクティブ」を「Java」に切り替えて、適当な「Javaプロジェクト」の「mainメソッドを持つクラス」に「ブレークポイント」を付けて、

f:id:ts0818:20201205164006p:plain

デバッグ(D)」>「Javaアプリケーション」を選択。

f:id:ts0818:20201205164331p:plain

 「切り替え(S)」を選択。

f:id:ts0818:20201205164521p:plain

 「パースペクティブ」が「デバッグ」に切り替わるので、「デバッグ」の「ビュー」で「javax.exe」の行を見つけて、

f:id:ts0818:20201205164645p:plain

「javaw.exe」上で右クリックし、「プロパティー(R)」を選択。 

f:id:ts0818:20201205164735p:plain

「プロセス情報」の「コマンド行(M):」に「クラスパス」が表示されてるようです。

f:id:ts0818:20201205164822p:plain

以下、抜粋。「クラスパス」は「 -classpath C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\workspace\one_hundred_nock\bin one_hundred_nock.first.nine.Typoglycemia」 って部分から「C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\workspace\one_hundred_nock\bin」になるみたいね。

C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\java\11\bin\javaw.exe -agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:64533 -javaagent:C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\eclipse\configuration\org.eclipse.osgi\413\0\.cp\lib\javaagent-shaded.jar -Dfile.encoding=UTF-8 -classpath C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\workspace\one_hundred_nock\bin one_hundred_nock.first.nine.Typoglycemia

とりあえず、「デバッグ」を停止で。

f:id:ts0818:20201205164953p:plain

中断した「デバッグ実行」の内容を、片付けときましょう。

f:id:ts0818:20201205165738p:plain

きれいになりました。

f:id:ts0818:20201205165858p:plain

 

ちなみに、Eclipseの場合、Javaの標準APIは、「JREシステム・ライブラリー」に配置されてる「jar」ファイル群ってことみたい。

f:id:ts0818:20201205202854p:plain

java.lang」パッケージは、自分の環境では「C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\java\11\lib\jrt-fs.jar」の中に配置されてるっぽい。

f:id:ts0818:20201205202607p:plain

エクスプローラー」からも確認できました。

f:id:ts0818:20201205203334p:plain

ただ、こやつらが「デバッグ実行」時の「クラスパス」に指定されてないように見えたんだけども、

デフォルトではJDK標準APIと拡張パッケージのみが場所を指定する必要がなくアクセス可能である。

クラスパス - Wikipedia

⇧ ってことみたいね。

つまり、上記の説明にあるように「JDK標準API」「拡張パッケージ」は何にもしなくても使えるようになってるみたい。上記以外については「クラスパス」に追加してあげる必要があるってことのようですね。

 

ちなみにちなみに、Eclipseの場合は、「[Eclipseワークスペース]\[プロジェクト名]\.classpath」ってファイルが存在し、

f:id:ts0818:20201206100728p:plain

自分の環境では、「C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\workspace\one_hundred_nock\.classpath」となっております。

f:id:ts0818:20201206101009p:plain

この「.classpath」 ってファイルに、

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
		<attributes>
			<attribute name="module" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="src" path="src"/>
	<classpathentry kind="output" path="bin"/>
</classpath>

⇧ 「クラスパス」が設定されてるっぽい。

8行目の「<classpathentry kind="src" path="src"/>」が「コンパイル対象のファイルまでのパス」、つまり「.java」ファイルまでのパスで、

9行目の「<classpathentry kind="output" path="bin"/>」が「コンパイル後のファイルが配置されるパス」、つまり「.class」ファイルが配置されるパスってことみたいね。

Eclipseの「プロジェクト」フォルダ内に適当なフォルダを作成して、そのフォルダを「.classpath」で指定するようにすれば、「クラスパス」も変更できるんではないでしょうか、たぶん。

 

あと、「デバッグ実行」時に「-agentlib」「-javaagent」のオプションも設定されてたんだけども、

waysaku.hatenablog.com

⇧ 「-agentlib」「-javaagent」については、上記サイト様がまとめてくださってますが、

Tiger からは JVMPI は Deprecated で、JVMTI が代りに使われます。

-agentlib/-agentpath -> JVMTI
-javaagent -> instrumentation

です。

https://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=26578&forum=12

JVMTI はデバッグとかプロファイルに使われるもので、C/C++ で記述します。
機能的には JVMTI = JVMPI + JVMDI + アルファ です。

https://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=26578&forum=12

instrumentation はクラスの再定義とか、バイトコードの書き換えとかをする
ために使用されます。こちらは Java で記述できます。

https://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=26578&forum=12 

⇧ ってことみたいで、何だろう、「フレームワーク」とかの開発とかに携われば利用する感じなのかな?

う~ん、用途を見出すのが難しい気が...


■結論

Javaの「クラスパス」については、

 ってな感じで、上記以外にも様々な要因が影響すると思われるので、まぁ、「クラスパス」の確認方法ってカオスよね...

Eclipse を使ってる場合、

www.366service.com

⇧ 「テスト環境」の「クラスパス」を設定することもあるみたいね。

 

JAVA_HOME」についても、

www.baeldung.com

⇧「OS」で異なる設定になりそうね...

 

紛らわしいんだけど、Eclipse自体も「JVM」で動いてるらしいんだけど、

aruo.net

⇧ 設定できたりするらしい。

eclipse.ini」に記載されてるんだとか。自分の環境では「C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\eclipse\eclipse.ini」におりました。

f:id:ts0818:20201206105212p:plain

eclipse.ini」確認してみました。

-vm
jre/bin/server
-product
org.eclipse.epp.package.jee.product
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vmargs
-Dosgi.requiredJavaVersion=1.8
-XX:+UseG1GC
-XX:+UseStringDeduplication
--add-modules=ALL-SYSTEM
-Dosgi.dataAreaRequiresExplicitInit=true
-Xverify:none
-javaagent:dropins/MergeDoc/eclipse/plugins/jp.sourceforge.mergedoc.pleiades/pleiades.jar
-javaagent:lombok.jar

⇧ 2行目の「jre/bin/server」がEclipseを起動する「JVM」を決定しているらしい。

自分の環境では「C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\eclipse\jre\bin\server\jvm.dll」におりました。

f:id:ts0818:20201206105727p:plain

⇧ まさかの「.dll」ファイル...

 

qiita.com

⇧ 上記サイト様を参考に確認してみた。

cd C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\eclipse\jre\bin\server

jvm.dllの中身を確認

"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\dumpbin.exe" /exports jvm.dll

f:id:ts0818:20201206110509p:plain

 

Microsoft (R) COFF/PE Dumper Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file jvm.dll

File Type: DLL

  Section contains the following exports for jvm.dll

    00000000 characteristics
    FFFFFFFF time date stamp
        0.00 version
           1 ordinal base
        3650 number of functions
        3650 number of names

    ordinal hint RVA      name

          1    0 00805568 ??_7?$AscendTreeCensusClosure@VFreeChunk@@V?$AdaptiveFreeList@VFreeChunk@@@@@@6B@
          2    1 007E2C60 ??_7?$AscendTreeCensusClosure@VMetablock@metaspace@@V?$FreeList@VMetablock@metaspace@@@@@@6B@
          3    2 00857398 ??_7?$CppVtableTesterA@VConstantPool@@@@6B@

...省略...

       3639  E36 00A24B18 gHotSpotVMTypeEntryTypeNameOffset
       3640  E37 009A6660 gHotSpotVMTypes
       3641  E38 003EBB10 jio_fprintf
       3642  E39 003EBBD0 jio_printf
       3643  E3A 003EBC50 jio_snprintf
       3644  E3B 003EBCA0 jio_vfprintf
       3645  E3C 003EBD10 jio_vsnprintf
       3646  E3D 009BC088 jvmciHotSpotVMAddresses
       3647  E3E 009BC078 jvmciHotSpotVMIntConstants
       3648  E3F 009BC080 jvmciHotSpotVMLongConstants
       3649  E40 009BBC68 jvmciHotSpotVMStructs
       3650  E41 009BC070 jvmciHotSpotVMTypes

  Summary

       AE000 .data
       55000 .pdata
      235000 .rdata
       38000 .reloc
        1000 .rsrc
      747000 .text
        3000 _RDATA

⇧ よく分からんけど、何かメモリとかに使用されるJVMの情報の参照先なんかが保存されてるんかね?

Wikipediaさんの「DLL(Dynamic Link Library)」の説明を見る限り、

ダイナミックリンクライブラリ (Dynamic Link Library: DLL、動的リンクライブラリ) は、ソフトウェアバイナリ形態の一種。動的リンクを使ったライブラリのこと。あるいは、Windowsで使用されるファイル形式を特に意図して、この語が用いられる場合もある。

ダイナミックリンクライブラリ - Wikipedia

Windowsにおけるダイナミックリンクライブラリのモジュールは、拡張子が「.dll」のファイルであるActiveXコントロールCOMコンポーネントの一種)に関しては、慣例的に「.ocx」という拡張子が付けられることもある(他にも、LightWaveプラグインファイルには慣例的に「.p」の拡張子が付けられるが、Windows版におけるファイルの中身自体はWin32 DLLそのものである)。DLLは本体ソフトウェアつまり実行プログラム(「.exe」拡張子を持つモジュール)によって実行時にロードされる。

ダイナミックリンクライブラリ - Wikipedia

Unix系OSでは /usr/lib や /lib などの下に通常置かれる、拡張子が「.so」のファイルである。バージョンによる差異の吸収を目的として、拡張子が「.so.バージョン番号」というファイルを実体として作成し、バージョン共通名の「.so」をその実体へのシンボリックリンクとすることが多い。

ダイナミックリンクライブラリ - Wikipedia

macOSでは拡張子として「.dylib」が使われる。

ダイナミックリンクライブラリ - Wikipedia

同じUnix系OSでも、SunOS はリンク時に Shared library を指定しなくて良い(つまり、実行時まで(Shared library 内にあるとされる)関数の名前解決がされるかどうか遅延させることが可能である)が、Solaris ではリンク時に Shared library を指定することで(Shared library 内にあるとされる)関数が名前解決されるかどうかリンカがチェックできるようにする必要がある(無論、Shared library なので、リンカは関数が名前解決されるかどうかチェックするのみでリンクはしない)。

ダイナミックリンクライブラリ - Wikipedia

⇧「OS」によって、Eclipseの「DLL(Dynamic Link Library)」の「拡張子」は異なるみたいね。WindowsでしかEclipse を使ったことないから、他のOSでEclipse を使った場合にどうなってるのか分からんけど...

Eclipse自体を起動するのには、

wiki.eclipse.org

If a JVM is installed in the eclipse/jre directory, Eclipse will use it; otherwise the launcher will consult the eclipse.ini file and the system path variable. Eclipse DOES NOT consult the JAVA_HOME environment variable.

https://wiki.eclipse.org/FAQ_How_do_I_run_Eclipse%3F

⇧「JAVA_HOME」の設定は不要なんだとか。

JAVA_HOME」ってのは、

stackoverrun.com

JAVA_HOMEは、Java自体では使用されません。いくつかのサードパーティ製の プログラム(Apache Tomcatなど)では、これらの環境の1つがJDKまたはJREのインストールディレクトリに設定されることが予想されます。 必要なソフトウェアを使用していない場合は、 JAVA_HOMEとJRE_HOMEを設定する必要はありません。

CLASSPATHは、Javaクラスのそれ 検索をロードすることと、Javaが通じなります ディレクトリおよび/またはJARファイルのリストを、含まれている環境変数です。通常、CLASSPATH環境変数 を設定する必要はありません。この環境を使用する代わりに、 変数を使用して、コマンドライン で-cpまたは-classpathオプションを使用して、javacコマンドおよびjavaコマンドを使用することができます。

PATHは、それが 実行するためにネイティブの実行可能プログラムを探しますオペレーティング・システム(Windows、 のMac OS XLinuxなど)で使用される環境変数です。コマンドプロンプトウィンドウでjavacとjavaコマンド と他のJDKツールを使用できるように、JDKインストール ディレクトリのbinサブディレクトリをPATHに追加する必要があります。 JDKのインストール の手順は、PATHの設定方法を説明しています。

https://stackoverrun.com/ja/q/5965986

⇧ あくまでも、「サードパーティ製のプログラム」のために設定するものらしいですね。

とは言え、

qiita.com

⇧ 上記サイト様によりますと、Eclipseの「Gradleプロジェクト」で参照する「JAVA_HOME」は設定できるみたいね。

 

Eclipseで使用してる「JDKJava Development Kit)」については、

itdoc.hitachi.co.jp

⇧ 上記サイト様が参考になるかと。

確認してみます。

「ウィンドウ(W)」>「設定(P)」を選択。

f:id:ts0818:20201206121817p:plain

Java」>「インストール済みのJRE」で確認できる模様。

f:id:ts0818:20201206121930p:plain

⇧ 自分の環境では「C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\java\11」が設定されておりました。

ここを変更すれば、Eclipseの「Java」に関連する「プロジェクト」で使用するJavaのバージョンとかも 変えられるってことですかね。

 

サードパーティ製のプログラム」が入り乱れるとカオスになりがちですし、Javaで開発する場合は、「サードパーティ製のプログラム」が否応なく関係してくる感じですかね...

少なくとも、「Application Server」や「ビルドツール(MavenやGradle)」なんかは昨今の開発では当たり前のように使われてそうですしね...

Eclipse以外の「IntelliJ IDEA」とか「NetBeans」、「Visual Studio Code」とかで「クラスパスの設定」がどうなるか知りたいっすな。

 

今回はこのへんで。