⇧ 皆々様、ご存知、お笑いコンビ「いつもここから」のネタですね、どうもボクです。
確かに、夕日が沈んでいく様子は「もの悲し」気分になりがちですが、「TOMMOROW(岡本真夜)」で「涙の数だけ強くなれるよ」って歌詞がありますが、「涙」と言えば、
19世紀末、ウィリアム・ジェームズとカール・ランゲという心理学者が提唱した「ジェームズ・ランゲ説」に、「悲しいから泣くのではない、泣くから悲しいのだ」という有名なフレーズがあります。彼らによると、涙という生理反応が生じた後、その反応に対する一種の解釈として悲しくなるというのです。ジェームズ・ランゲ説が感情のすべてを説明できるわけではありませんが、触覚によって生理反応を演出することで、心の動きをある程度操作できることはわかっています。
⇧「ジェームズ・ランゲ説」は有名ですが、
この説の反対を主張するのが「キャノンバード説」というものらしい。
脳中枢で生じるプロセスが抹消反応に先行するとする。ジェームズ=ランゲ説に対して、「悲しいから泣く」と説明される。
「鶏が先か、卵が先か」じゃないけども、「身体反応が先か、感情反応が先か」ってことが議論されてきたそうな。
「泣くから悲しい」「悲しいから泣く」確かに、どっちが本来の挙動なんでしょうね?
ただ、「エレファントカシマシ」の「宮本浩次」さんの「冬の花」の歌詞で、
悲しくって泣いてるわけじゃあない 生きてるから涙が出るの
⇧「生きてるから涙が出るの」って言葉が出てくるんですが、衝撃ですね...
「悲しいから泣いてるんじゃない」んだと、「生きてる」から「涙」が出るんだと。
確かに、「涙」は様々な要因で起こる現象でしょうけど、「生きてる」からこそですからね、だって「嬉し涙」って言葉もあるぐらいだし、「涙」が出るのは「悲しい」時だけじゃないんよね。
「冬の花」良い歌ですね。
というわけで、今回は、Javaです。レッツトライ~。
クラスパスって?
Javaのクラスパスが本当、分かり辛いんだわ...
どうにかならんもんかね?っていうぼやきつつ、確認して参りましょう。
Oracleさんによりますと、
クラスパスは、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...
set CLASSPATH=classpath1;classpath2...
ってことみたいですと。
sdkTool
コマンド行ツール (java
、javac
、javadoc
、apt
など) です。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 を使ってる場合は、
⇧上記サイト様によりますと、「パースペクティブ」で「デバッグ」を選択して、「ビュー」の「デバッグ」に表示される「javaw.exe」上で右クリックして「プロパティ」を選択すれば確認できるらしい。(本番環境にデプロイされたら、全く異なる「クラスパス」になるんだとは思われますが...)
ただ、「デバッグ」を実行してないと「javaw.exe」は表示されないっぽいですかね。
「パースペクティブ」を「Java」に切り替えて、適当な「Javaプロジェクト」の「mainメソッドを持つクラス」に「ブレークポイント」を付けて、
「切り替え(S)」を選択。
「パースペクティブ」が「デバッグ」に切り替わるので、「デバッグ」の「ビュー」で「javax.exe」の行を見つけて、
「javaw.exe」上で右クリックし、「プロパティー(R)」を選択。
「プロセス情報」の「コマンド行(M):」に「クラスパス」が表示されてるようです。
以下、抜粋。「クラスパス」は「 -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
とりあえず、「デバッグ」を停止で。
中断した「デバッグ実行」の内容を、片付けときましょう。
きれいになりました。
ちなみに、Eclipseの場合、Javaの標準APIは、「JREシステム・ライブラリー」に配置されてる「jar」ファイル群ってことみたい。
「java.lang」パッケージは、自分の環境では「C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\java\11\lib\jrt-fs.jar」の中に配置されてるっぽい。
「エクスプローラー」からも確認できました。
ただ、こやつらが「デバッグ実行」時の「クラスパス」に指定されてないように見えたんだけども、
⇧ ってことみたいね。
つまり、上記の説明にあるように「JDK標準API」「拡張パッケージ」は何にもしなくても使えるようになってるみたい。上記以外については「クラスパス」に追加してあげる必要があるってことのようですね。
ちなみにちなみに、Eclipseの場合は、「[Eclipseのワークスペース]\[プロジェクト名]\.classpath」ってファイルが存在し、
自分の環境では、「C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\workspace\one_hundred_nock\.classpath」となっております。
この「.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」のオプションも設定されてたんだけども、
⇧ 「-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の「クラスパス」については、
- 環境変数「CLASSPATH」を設定してる場合は、OSによって「クラスパス」は変わり得ると思われる。
- 実行するソフトウェアで「クラスパス」は変わり得ると思われる。
- Eclipse ←今回確認
- IntelliJ IDEA
- NetBeans
- Visual Studio Code
- 実行するミドルウェア(Application Server)で「クラスパス」は変わり得ると思われる。
ってな感じで、上記以外にも様々な要因が影響すると思われるので、まぁ、「クラスパス」の確認方法ってカオスよね...
Eclipse を使ってる場合、
⇧ 「テスト環境」の「クラスパス」を設定することもあるみたいね。
「JAVA_HOME」についても、
⇧「OS」で異なる設定になりそうね...
紛らわしいんだけど、Eclipse自体も「JVM」で動いてるらしいんだけど、
⇧ 設定できたりするらしい。
「eclipse.ini」に記載されてるんだとか。自分の環境では「C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\eclipse\eclipse.ini」におりました。
「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」におりました。
⇧ まさかの「.dll」ファイル...
⇧ 上記サイト様を参考に確認してみた。
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
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で使用されるファイル形式を特に意図して、この語が用いられる場合もある。
Windowsにおけるダイナミックリンクライブラリのモジュールは、拡張子が「.dll」のファイルであるActiveXコントロール(COMコンポーネントの一種)に関しては、慣例的に「.ocx」という拡張子が付けられることもある(他にも、LightWave用プラグインファイルには慣例的に「.p」の拡張子が付けられるが、Windows版におけるファイルの中身自体はWin32 DLLそのものである)。DLLは本体ソフトウェアつまり実行プログラム(「.exe」拡張子を持つモジュール)によって実行時にロードされる。
Unix系OSでは /usr/lib や /lib などの下に通常置かれる、拡張子が「.so」のファイルである。バージョンによる差異の吸収を目的として、拡張子が「.so.バージョン番号」というファイルを実体として作成し、バージョン共通名の「.so」をその実体へのシンボリックリンクとすることが多い。
macOSでは拡張子として「.dylib」が使われる。
同じUnix系OSでも、SunOS はリンク時に Shared library を指定しなくて良い(つまり、実行時まで(Shared library 内にあるとされる)関数の名前解決がされるかどうか遅延させることが可能である)が、Solaris ではリンク時に Shared library を指定することで(Shared library 内にあるとされる)関数が名前解決されるかどうかリンカがチェックできるようにする必要がある(無論、Shared library なので、リンカは関数が名前解決されるかどうかチェックするのみでリンクはしない)。
⇧「OS」によって、Eclipseの「DLL(Dynamic Link Library)」の「拡張子」は異なるみたいね。WindowsでしかEclipse を使ったことないから、他のOSでEclipse を使った場合にどうなってるのか分からんけど...
Eclipse自体を起動するのには、
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.
⇧「JAVA_HOME」の設定は不要なんだとか。
「JAVA_HOME」ってのは、
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 X、Linuxなど)で使用される環境変数です。コマンドプロンプトウィンドウでjavacとjavaコマンド と他のJDKツールを使用できるように、JDKインストール ディレクトリのbinサブディレクトリをPATHに追加する必要があります。 JDKのインストール の手順は、PATHの設定方法を説明しています。
⇧ あくまでも、「サードパーティ製のプログラム」のために設定するものらしいですね。
とは言え、
⇧ 上記サイト様によりますと、Eclipseの「Gradleプロジェクト」で参照する「JAVA_HOME」は設定できるみたいね。
Eclipseで使用してる「JDK(Java Development Kit)」については、
⇧ 上記サイト様が参考になるかと。
確認してみます。
「ウィンドウ(W)」>「設定(P)」を選択。
「Java」>「インストール済みのJRE」で確認できる模様。
⇧ 自分の環境では「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」とかで「クラスパスの設定」がどうなるか知りたいっすな。
今回はこのへんで。