S-JIS[2003-07-06/2014-03-20] 変更履歴

Javaアプリケーション

Javaアプリケーションは Javaソースを(C言語やC++等と同様に)コンパイルし、コンパイルして出来たファイルを実行するもの。
(実際にはJavaで作った全てのプログラムがコンパイル・実行するものだけれども、ここではJavaアプレットサーブレットと区別する意味で「Javaアプリケーション」と呼んでいる)

javacコマンドでコンパイルし、javaコマンドで実行する。
実行は、クラス内のpublic static void main(String[] args)メソッド(あるいは...)から行われる。
JDK1.5から、main()が実行される前にメソッドpremain()を呼ぶこともやろうと思えば出来るようになった。[2007-11-12]

  • javap…クラスファイルの情報 [/2010-01-15]
  • jps…プロセス一覧表示 [/2010-03-25]
  • jstack…スレッドダンプ [2009-12-12]
  • jconsole…GUIで情報表示 [2009-12-12]

ソース内にパッケージの指定が無い場合のコンパイル実行

>javac ソースファイル名
>java クラス名

ソース内にパッケージの指定がある場合のコンパイルと実行

>javac パッケージ名\ソースファイル名
>java パッケージ名.クラス名

例えば「c:\java\sample1\pac\func\Start.java」というソースファイルが「package pac.func;」という宣言をしている場合、コンパイルは

>cd c:\java\sample1\pac\func
>javac Start.java
>cd c:\java\sample1
>javac pac\func\Start.java

のどちらでも出来るが、実行はパッケージのルートディレクトリーに移動して

>cd c:\java\sample1
>java pac/func/Start
>cd c:\java\sample1
>java pac.func.Start

で行う。(実行する時には拡張子“.class”は不要。ファイル名を指定するのではなく、クラス名を指定する為)

他の場所で実行すると、下のようなエラーになる。

>cd c:\java\sample1\pac\func
>java Start
Exception in thread "main" java.lang.NoClassDefFoundError: Start (wrong name: pac/func/Start)
        at java.lang.ClassLoader.defineClass0(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:486)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:111)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:248)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:297)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:286)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:253)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:313)

Start.classというクラスファイル自体は見つけたが、javaコマンドの引数には「Start」しか書かれていない為、JavaVMはデフォルトパッケージ(パッケージ無し)の「Start」というクラスを想定していた。
にも関わらず(Start.class内に保持されている)実際のクラスは「pac.func.Start」というパッケージ付きのクラスなので、一致していない。
というエラー。[2008-12-20]

また、クラスパスを指定することで、カレントディレクトリーを移動する必要はなくなる。[2006-05-14]

>java -cp c:\java\sample1 pac.func.Start

jarファイル化した場合は、クラスパスにそのjarファイルを指定する。
(jarファイルを作るには、build.xmlを作っておくのが便利)[2006-06-17]

>java -cp c:\java\sample1.jar pac.func.Start

なお、(Windows版には)javaコマンドに似たjavawコマンドというものがある。[2007-06-30]
これは、実行時にコンソール(ウィンドウ)を開かない。なので、javawを使って実行した場合はSystem.out.println()で出力したメッセージはどこにも出ない。


クラスパスを指定する例

大規模なアプリケーションになってくると、クラスを複数のjarファイルから取ってきて使用したりする。[2009-02-20]
その場合、全てのjarファイルがクラスパスに入っている必要がある。
起動オプションでは、区切り文字(Windowsではセミコロン「;」、UNIXではコロン「:」)で区切ることにより、複数のjarファイル(やディレクトリー)を指定することが出来る。

>javac -classpath C:\sample\lib\abc.jar;C:\sample\lib\def.jar 〜
>java  -classpath C:\sample\lib\abc.jar;C:\sample\lib\def.jar 〜
>javac -classpath /sample/lib/abc.jar:/sample/lib/def.jar 〜
>java  -classpath /sample/lib/abc.jar:/sample/lib/def.jar 〜

いちいちパスを列挙するのは大変なので、DOSのfor文UNIXのfor文等を使って(バッチ(シェル)化して)jarファイル名を集めてくるようにすることも多い。

Windows UNIX
@echo off
goto main

:add

set CP=%CP%;%1
exit/b

:main
set CP=
for %%i in (C:\sample1\lib\*.jar) do call :add %%i
for %%i in (C:\sample2\lib\*.jar) do call :add %%i

echo %CP%
java -cp %CP% 〜

わざわざcallを使う理由

#!/bin/bash


add()
{
	CP=$CP:$1
}


CP=
for i in /sample1/lib/*.jar; do add $i; done
for i in /sample2/lib/*.jar; do add $i; done

echo $CP
java -cp $CP 〜
※パスにスペースが含まれていないのが前提
for文をまとめることも出来る。
for %%i in (
	C:\sample1\lib\*.jar
	C:\sample2\lib\*.jar
) do call :add %%i
for文をまとめることも出来る。
for i in\
	/sample1/lib/*.jar\
	/sample2/lib/*.jar
do add $i; done
※doの直前の行の末尾には行継続文字「\」を付けてはいけない

JDK1.6からはクラスパスの指定にワイルドカードを使えるようになった為、「特定ディレクトリーに入っている全てのjarファイル」に関しては、自分で(バッチシェルで)用意する必要は無くなった。[2010-01-09]
javacコマンドでもjavaコマンドでも使用可能。

  備考 参考
Windows
javac -cp C:\sample1\lib\*;C:\sample2\lib\* ファイル名
java -cp .;C:\sample1\lib\*;C:\sample2\lib\* クラス名
 
UNIX
javac -cp "/sample1/lib/*:/sample2/lib/*" ファイル名
java -cp ".:/sample1/lib/*:/sample2/lib/*" クラス名
UNIXで「*」を使う際には、念の為にクォーテーションで囲んでおく方がいいかな。
(「*」に何らかの文字がくっついているとクォーテーションは不要なようだが)

クラスパスワイルドカード「*」はjavacやjavaコマンドが解釈し、そのディレクトリーの拡張子「jar」のファイルの具体的なファイル名に展開される。
例えば「sample/a.jar」「sample/b.jar」「sample/c.zip」が在る場合、「sample/*」は、「sample/a.jar;sample/b.jar」(Windowsの場合)となる。
システムプロパティーjava.class.pathで取得されるのは展開された状態になる。
部分マッチするような指定は出来ない。すなわち「*.jar」や「*.zip」、「a*.jar」「a*」といった指定は展開/検索対象にならない。


隠れた依存クラスを指定しない場合のコンパイル・実行

「class C1」があり、「class C2 extends C1」で「class C3 extends C2」のとき、C3をコンパイルする為には、C2の他にC1もクラスパスに入っている必要がある。[2009-02-02]

C3.javaのコンパイルの際にC1.classがクラスパスに入っていないと、以下のようなコンパイルエラーになる。

classes3> javac -cp ../classes2 C3.java
C3.java:2: C1 にアクセスできません。
C1 のクラスファイルが見つかりません
public class C3 extends C2 {
       ^
エラー 1 個

ちなみに、Eclipse3では以下のようなエラーになる。
(C3に対して)型 C3 の階層は不整合です
(C2に対して)型 C1 を解決できません。 必要な .class ファイルから間接的に参照されています

C1とC2のクラスパスを両方指定してやるとコンパイルできる。

classes3> javac -cp ..\classes2;..\classes1 C3.java

実行時に(C3と)C2のクラスパスだけ入れていてC1のクラスパスが入っていないと、以下のような例外が発生する。

classes3> java -cp .;..\classes2 C3
Exception in thread "main" java.lang.NoClassDefFoundError: C1
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(Unknown Source)
        at java.security.SecureClassLoader.defineClass(Unknown Source)
〜

C3のソース上には(C2が依存している)C1は出てこないので、厄介なエラーだなぁ。


コンパイルオプション

javacコマンド拡張子javaのファイルをコンパイルすると、拡張子classのファイル(バイトコード)が生成される。
ドキュメントには書かれていないが、javacコマンドは、コンパイルが成功すると0、失敗すると1を返すようだ。(Windows→%ERRORLEVEL%、UNIX→$?

オプション 説明 更新日
-encoding MS932 ソース内の文字列がShiftJISであることを明示する(MS932はSJISの一種で、もっと厳密な体系)。
普通は自動的に判別してくれるので、指定不要。厳密に言えば、ソース内の文字がUNICODE以外のときは明示的に指定しなきゃいけないらしいけど…。
 
-d ディレクトリ コンパイルした結果(classファイル)を格納するディレクトリを指定する。
ここで指定したディレクトリの下に、package文で指定したパッケージの構成と同じサブディレクトリが作られる。
逆に、ソースファイル自身はパッケージと同じディレクトリ構成に居る必要はない。実際は同じ階層を構築することが多いが。
この指定が無いと、classファイルはjavaファイルと同じ場所に作られる。
 
-classpath クラスパス; クラスパス(CLASSPATH)を指定する。
コンパイル時に使用(参照)するクラスの在るディレクトリーjarファイルを、パス区切り(Windowsの場合はセミコロン「;」、UNIXならコロン「:」)で複数指定できる。
Eclipseのビルドパス
JDK1.6では、クラスパスワイルドカード「*」が使えるようになった。
2010-01-09
-cp クラスパス; -classpathと同じだが、JDK1.5以降。 2009-02-02
-source バージョン コンパイルするソースが準拠しているJDKのバージョン(使用する文法のバージョン)を指定する。
これにより使える文法が変わってくる。例えばアサーションを使う時には1.4以上を指定する必要があるし、enum等のJDK1.5の新機能を使う時は1.5以上(1.5または5)を指定する必要がある。
JDK1.6準拠なら1.6(または6)を指定する。(Eclipse3.2では5.0/6.0という表記。Eclipse3.4では1.5/1.6)
省略時のバージョン
2010-01-09
-target バージョン コンパイルして出来たclassが実行できるJavaVMのJREのバージョンを指定する。値は-sourceと同様。
省略時のバージョン
2007-05-15
-parameters メソッド(やコンストラクター)の引数名をclassファイルに保持する。JDK1.8以降。
Paramerters#getName()
2014-03-20
-Jオプション javacが使用するjavaコマンド(javacと同バージョンのjava)へのオプションを指定する。
(例えば「javac -J-version」は、「java -version」の意味。複数のバージョンのJDKがインストールされている場合、「javac -J-version」と「java -version」では、異なる実体(バージョン)のjavaコマンドが実行される可能性が有る)
2007-05-15
どうも、javacも内部ではjavaコマンドを使ってコンパイル用クラスを実行しているようだ。
例えば「javac Sample.java」→「java com.sun.tools.javac.Main Sample.java」といった感じ。
javac -J-version」を実行すると、実際は「java -version com.sun.tools.javac.Main」となり、-versionではその他の引数は無視されるので正しく実行されるようだ。
試しに「javac -J-cp -JC:\temp -JSample zzz」を実行してみると、「java -cp C:\temp Sample com.cun.tools.javac.Main zzz」となって実行されているっぽい。
(この例では、Sampleクラスが実行され、その第1引数が「com.sun.tools.javac.Main」になる!)
2009-11-14
-version JDK1.6以降。javacのバージョンを表示する。 2008-07-25
-verbose 使用するクラス等の詳細情報を表示する。 2010-01-10
-Xlint 推奨の警告を有効にする。細かいエラーチェックを行い、警告を出してくれる。→使用例
ソース上で警告を抑止する方法
2007-06-12

Antのjavac
→Sunのjavac - Javaプログラミング言語コンパイラ
実行時コンパイルクラス(JavaCompiler)


-sourceと-targetの関係

-source-targetを省略した場合は、コンパイラー(javac)のバージョンに応じたバージョンになる。[2008-07-16]

-sourceに1.4を指定して-targetに1.5を指定した場合、使用できる文法はJDK1.4までの文法だが、出来上がるクラスファイルはJRE1.5向けになる。
すなわち、Stringの+演算子StringBuilderに置き換えられる。

-sourceに1.4を指定して-targetも1.4だった場合、(JDK1.5以降のjavacであっても)Stringの+演算子StringBufferに置き換えられる。
ただし、コンパイル時に指定している標準ライブラリー(JDK)が1.5のものだった場合、JDK1.5で追加されたクラスやメソッド(System.out.printf()java.util.Queue)は使用できる。

Sample14.java:

import java.util.Queue;
import java.util.LinkedList;

public class Sample14 {
	public static void main(String[] args) {
		Queue q = new LinkedList();
		q.add("abc");
		q.add("def");

		System.out.printf("%s, %s%n", new Object[]{"abc", "def"});	//可変長引数は配列形式で呼び出せる
	}
}

可変長引数printf("%s, %s%n", "abc", "def")」はJDK1.5以降でないと使えない(「-source 1.4」では使えない)が、
配列形式の呼び出しprintf("%s, %s%n", new Object[]{"abc", "def"})」であればJDK1.4でも使える。

コンパイル:

>which javac
javac=C:\Program Files\Java\jdk1.6.0\bin\javac.exe	…使うのはJDK1.6のコンパイラー

>javac -source 1.4 -target 1.4 Sample14.java		…JRE1.4用にコンパイル

>javap -v Sample14
Compiled from "Sample14.java"
public class Sample14 extends java.lang.Object
SourceFile: "Sample14.java"
minor version: 0
major version: 48クラスファイルのバージョンはJRE1.4
〜

実行:

>java -version:1.4 Sample14		…JRE1.4のjavaコマンドで実行
Exception in thread "main" java.lang.NoClassDefFoundError: java/util/Queue

>java -version:1.5 Sample14		…JRE1.5のjavaコマンドで実行
abc, def

JDK1.4の標準ライブラリーにはjava.util.Queueは存在しないので、実行時にNoClassDefFoundErrorが発生する。
(コンパイル時にはJDK1.6のコンパイラーを使用しているので、JDK1.6のライブラリーが使われている(すなわちjava.util.Queueが存在しているのでエラーにならない))

しかしJDK1.5のライブラリーを使ってわざわざJDK1.4向けにコンパイルしても、JRE1.5以降のjavaコマンドでしか実行できないので、意味無いよなー(苦笑)
JDK1.4のjavacに「-classpath "C:\Program Files\Java\jdk1.5.0_09\jre\lib\rt.jar"」を指定しても、バージョン違いのエラー「クラスファイルのバージョン 49.0 は不正です。48.0 であるべきです。」になってコンパイルできないし。


実行時オプション

「java -help」や「java -X」でヘルプが表示される。
ドキュメントには書かれていないが、javaコマンドは、実行が成功すると0(System.exit()で値を設定していればその値)、失敗すると1を返すようだ。(Windows→%ERRORLEVEL%、UNIX→$?

オプション 説明 更新日
-version 実行されるJavaVMのバージョン(1.4とか1.6とか)を表示して終了する 2007-05-15
-version:バージョン 実行するJavaVMのバージョンを指定する。 2007-06-28
-showversion 実行されるJavaVMのバージョン(1.4とか1.6とか)を表示して続行する 2010-01-09
-classpath クラスパス;
-cp
クラスパス;
クラスパス(CLASSPATH)を指定する。
実行時に使用するクラスの在る、ディレクトリーjarファイル
パス区切り(Windowsの場合はセミコロン「;」、UNIXならコロン「:」)で複数指定できる。
JDK1.6では、クラスパスワイルドカード「*」が使えるようになった。
ここで指定されたクラスパスはシステムプロパティーjava.class.pathで取得できる。
2010-01-09
-jar 実行可能jarファイル 実行可能jarファイルを実行する。 2009-01-15
-client クライアントのVMで実行(デフォルト)  
-server サーバーのVMで実行(メモリーを大量に使う代わりに速くなる)  
-hotspot マシンにネイティブなコードに変換して実行(クライアントとして)
…でもJRE1.4以降では無意味(-clientの指定と同じ)らしい。
2008-08-10
-ea アサーションを有効にする。「-ea」の代わりに「-enableassetions」でも可。  
-Dシステムプロパティー=値 システムプロパティーを設定する。設定したプロパティーはSystem#getProprty()で取得できる。 2008-07-30
-Djava.system.class.loader=クラス クラスローダーを指定する。 2007-11-12
-javaagent:jarファイル= 事前実行クラス(premain()のあるクラス)を指定する。(JDK1.5以降) 2007-11-12
-agentlib デバッグ実行の指定(JDK1.5以降) 2009-01-15
オプション 説明
-verbose:class クラスがロードされた時に、そのことを出力する。[2010-01-09]  
-verbose:gc GCが実行された時、その状態を標準出力に出力する。  
-Xms<size> 初期ヒープサイズの指定。空きメモリーの80%くらいがよい。 -Xms256m
-Xmx<size> 最大ヒープサイズの指定。初期ヒープサイズと同じがよい。 -Xmx256m
-XX:NewSize=<size> GC新規割当サイズ。ヒープサイズの1/4〜1/3がよい。  
-XX:MaxNewSize=<size> GC新規割当時の最大サイズ。NewSizeと同じがよい。  
-XX:SurvivorRatio=<値> GC新規割当領域比率。2(推奨)〜8。  
-Xincgc GCの実行時間を10ms以内に抑えるオプション。サーバー向けではない  
-Xdebug
-Xrunjdwp
デバッグ実行の指定(JDK1.4)。JDK1.5で-agentlibに変わった。[2009-01-15]  

→Sunのjava - Javaアプリケーション起動ツール


クラスファイル情報

JDKjavapというコマンドを使用することで、コンパイルされたclassファイルの情報を見ることが出来る。[2007-05-26]

>javap 〔オプション〕 クラス名

クラス名の指定の仕方は、javaコマンドで実行するクラスを指定する方法と同様。
つまりクラスファイルの置かれているルートディレクトリーからパッケージ名付き(FQCN)でクラス名を指定する。

>cd C:\temp\classes
>javap jp.hishidama.sample.Sample

しかしjavaコマンドと異なり、そのクラスファイルがある場所で実行することも出来る。[2010-01-15]
(あくまでもファイル名指定ではなくクラス名指定なので、拡張子「.class」は付けない)

>cd C:\temp\classes\jp\hishidama\sample
>javap Sample

あとは、クラスパスを指定することも出来る。[2010-01-15]

>javap -classpath C:\tmep\classes jp.hishidama.sample.Sample

標準のクラス(java.lang.String等)は、クラスパス等を特に指定しなくても、javapが実行できる場所ならどこでも参照できる。[2007-09-26]

>javap java.lang.String
オプション 説明
-help javapのオプション一覧を表示する。
-public
-protected
-package
-private
それぞれの属性(ものによっては下位レベルも含む)のメンバーだけ表示する。
-c 逆アセンブル。インストラクションコードを表示する。
-s メンバーのシグニチャーを表示する。JNIメソッドフィールドを扱いたいときに便利。
-verbose
-v
詳細な情報表示。実行可能バージョンコンスタント(定数)プール等も表示される。
-classpath クラスパスの指定。(-cpオプションは無い)[2010-01-15]

クラス名(パッケージ名)や、どんなメンバー(メソッド・フィールド)が存在しているかを知るだけなら オプションは何も付ける必要はない。
逆コンパイルしてJavaソースの形で見たいならば、jadが便利。

→Sunのjavap - Javaクラスファイル逆アセンブラ


Javaバージョン

javacでコンパイルするとclassファイルが作られるが、classファイルの中には「どのバージョンのJavaVMで実行できるか」という“Javaクラスの形式”のバージョンが書かれる。[2007-05-15]
JavaVM(javaコマンド)では実行できるバージョンが限られており、自分より新しいバージョンで作られたclassファイルは実行することが出来ない (古すぎてもダメ)。
(実行しようとすると、「java.lang.UnsupportedClassVersionError: クラス名 (Unsupported major.minor version Mj.Mi)」の例外が発生する。Mj.Miは、 対象クラスのメジャーバージョンとマイナーバージョン。→native2asciiの例

JavaVMのバージョン[/2014-03-19]
JRE(JavaVM)
仕様バージョン
VMがサポートしている
Javaクラスの形式
のバージョン

(メジャーバージョン.
マイナーバージョン)
1.4 48.0
1.5 49.0
1.6 50.0
1.7 51.0
1.8 52.0

classファイルのメジャーバージョン/マイナーバージョンは、javacの-targetで指定した対象JavaVMバージョンの値によって異なってくる。-targetを省略した場合は-sourceの値に左右される。
-targetで指定するのは1.4とか1.5とか1.6というJREの仕様バージョンだが、classファイル内に保持されている値は48.0とか49.0とか50.0という数字(Javaクラスの形式のバージョン)。

生成されるバージョンの対応表(試行結果)[/2014-03-19]
-sourceの指定 -targetの指定 JDK(javac)のバージョン
1.4.0 1.4.2 1.5.0 1.6.0 1.7.0 1.8.0
なし なし 46.0 46.0 49.0 50.0 51.0 52.0
1.2以下 1.2 × 46.0 46.0 46.0 46.0 46.0△
1.3以下 1.3 47.0 47.0 47.0 47.0 47.0 47.0△
1.4以下 1.4 48.0 48.0 48.0 48.0 48.0 48.0△
1.5以下 1.5 × × 49.0 49.0 49.0 49.0△
1.6以下 1.6 × × × 50.0 50.0 50.0
1.7以下 1.7         51.0 51.0
1.8 1.8           52.0
1.1 なし × × × × × ×
1.2 なし × 46.0 48.0 48.0 48.0 48.0△
1.3 なし 46.0 46.0 48.0 48.0 48.0 48.0△
1.4 なし 48.0 48.0 48.0 48.0 48.0 48.0△
1.5 なし × × 49.0 50.0 51.0 52.0△
1.6 なし × × × 50.0 51.0 52.0
1.7 なし         51.0 52.0
1.8 なし           52.0

つまり、-targetを指定すれば、当然そのターゲットJavaVM向けのバージョンになる。
-sourceのみを指定した場合は、そのバージョンで動く(その時点での)なるべく最新のバージョンになる。
何も指定しなかった場合は、(Sunがサポートしても良いと思っている最古の?/Sunが推奨しようと思っている?)デフォルトのバージョンになる。
(JDK1.4までは「なるべく古いJREでも動くように」。JDK1.5からは「なるべく新しいJREでも動くように」という考えっぽい?)
のかな?

ターゲットのバージョンによってはclassファイルの中身(仕様・フォーマット)が違ったりするようで、新しく増えた命令とかがあったりするみたい。バージョンにそぐわない命令があったり、変な状況(ftpに失敗してclassファイルが壊れたり)で実行したりするとjava.lang.ClassFormatErrorが出るらしい。


JDK1.5以上のjavapを使えば、classファイルの実行可能バージョンを表示することが出来る。

>javap -v Test		…Test.classを表示する例。-vは-verboseのことらしい。
Compiled from "Test.java"
public class Test extends java.lang.Object
SourceFile: "Test.java"
minor version: 0
major version: 50

50.0だと、50.0に対応しているJavaVM(つまりJRE1.6のjavaコマンド)で実行できる、ということになる。
ちなみに、JDK1.4.0のjavapではバージョンは表示されず、JDK1.4.2_13では正しい値が表示されない(メジャーバージョンの箇所にマイナーバージョンの値がそのまま出てた(爆))

UNIXの場合は、fileコマンドでもclassファイルのバージョンを知ることが出来る。

なお、classファイルの中をバイナリーエディターで見てみると、 先頭部分が以下のようになっている。

00000000 : CA FE BA BE 00 00 00 32  00 1D 0A 00 06 00 0F 09
                       ~~~~~ ~~~~~
                       ↑    ↑メジャーバージョン:十六進数の0032十進数の50
                       ↑マイナーバージョン:0000

バージョンの表示方法
対象 コマンド 確認できる値の例 備考
開発環境 JDK javac -version 1.6.0 JDK1.6以降
javac -J-version 1.6.0-b105  
実行環境 JRE java -version
java -showversion
1.6.0_01-b06  
クラス class javap -v クラス名 50.0  

システムプロパティーでも実行中のJavaVMのバージョン情報が保持されている。[/2011-07-30]

システムプロパティー 値の例(JDK1.6) 値の例(JDK1.7) 内容 備考
java.class.version 50.0 51.0 “Javaクラスの形式”のバージョン 実行可能なclassファイルのバージョンと思われる
java.specification.name Java Platform API Specification Java Platform API Specification JREの仕様バージョン 実行可能な仕様を示すバージョン
java.specification.version 1.6 1.7
java.specification.vendor Sun Microsystems Inc. Oracle Corporation
java.version 1.6.0_02 1.7.0    
java.vendor Sun Microsystems Inc. Oracle Corporation
java.vendor.url http://java.sun.com/ http://java.oracle.com/
java.vm.name Java HotSpot(TM) Client VM Java HotSpot(TM) Client VM JavaVMのバージョン  
java.vm.version 1.6.0_02-b06
11.3-b02
21.0-b17
java.vm.vendor Sun Microsystems Inc. Oracle Corporation
java.runtime.name Java(TM) SE Runtime Environment Java(TM) SE Runtime Environment JREのバージョン JavaVMの詳細なバージョン
java.runtime.version 1.6.0_13-b03 1.7.0-b147
java.vm.specification.name Java Virtual Machine Specification Java Virtual Machine Specification JavaVMの仕様バージョン  
java.vm.specification.version 1.0 1.7
java.vm.specification.vendor Sun Microsystems Inc. Oracle Corporation
java.vm.info mixed mode, sharing mixed mode, sharing    
java.home C:\Program Files\Java\jre1.6.0_02 C:\Program Files\Java\jdk1.7.0\jre Javaのインストール先ディレクトリー  

1.6とかのjavaのバージョンと、それがサポートしている50.0とかの数値との対応を(実際に試す以外に)どうやって知るのかは不明…。


実行したいバージョンの指定

ちなみに、1つのマシンに複数バージョンのJREがインストールされている場合、実行したいバージョンをjavaコマンドの-versionオプションで指定することが出来る。[2007-06-28]

> java -version:1.6 Test
> java -version:1.6.0 Test
> java -version:1.6.0_01 Test
> java -version:1.6.0_1 Test

エラーとなる例:

> java -version:1.4.2 Test
Unable to locate JRE meeting specification "1.4.2"	…1.4.0はOKなのに、1.4.2は存在していてもNG
						 存在しているバージョンを完全に指定(1.4.2_13)すればOK

jps

jpsは、JDK1.5から使えるようになったらしい、実行中のJavaアプリケーションのプロセスIDを表示するツール。[2009-12-12]
Windowsのtasklist、UNIXのpsのJavaプログラム専用バージョンといったところか。

tasklistで「tasklist | findstr java」とやると、普通にjava.exeやjavaw.exeで実行しているものは出てくるが、eclipse.exermiregistry.exeで実行したものは出てこないので、jpsの方が便利。

オプション 説明 実行例
-help ヘルプ(オプション一覧)が表示される。
> jps -help
usage: jps [-help]
       jps [-q] [-mlvV] [<hostid>]

Definitions:
    <hostid>:      <hostname>[:<port>]
なし プロセスIDと実行クラス名が表示される。
(右の例の2720はEclipse3.4)
> jps
2588 Jps
2664 RegistryImpl
2720
-l 実行クラス名が完全修飾名(FQCN)で表示される。
> jps -l
1780 sun.tools.jps.Jps
2664 sun.rmi.registry.RegistryImpl
2720
-q プロセスIDのみ表示される。
(実行クラス名が表示されない)
> jps -q
3180
2664
2720
-v 詳細情報(実行時オプション)が表示される。
> jps -v
2664 RegistryImpl -Denv.class.path=.;C:\Program Files\Java\jdk1.6.0_13\lib\tools.jar;〜 -Dapplication.home=C:\Program Files\Java\jdk1.6.0_13 -Xms8m
2652 Jps -Denv.class.path=.;C:\Program Files\Java\jdk1.6.0_13\lib\tools.jar;〜 -Dapplication.home=C:\Program Files\Java\jdk1.6.0_13 -Xms8m
2720 -Dosgi.requiredJavaVersion=1.5 -Xms256m -Xmx256m -Declipse.cvs.anon=true -javaagent:dropins/MergeDoc/eclipse/plugins/jp.sourceforge.mergedoc.pleiades/pleiades.jar -XX:MaxPermSize=256m
-lv -lと-vの組み合わせ。  

jpsの仕組みは、各Javaアプリケーションが作成した情報ファイルをただ集めてきて表示しているだけらしい。[2010-03-25]

  1. Javaアプリケーションが起動すると、環境変数TMP(無ければTEMP)が指しているディレクトリーの直下に
    「hsperfdata_ユーザー名」というディレクトリーを作成し、そのディレクトリー内に
    プロセスIDをファイル名とする情報ファイルを作成する。
  2. jpsが実行されると、環境変数TMP(無ければTEMP)の直下の「hsperfdata_」で始まる全ディレクトリーを探す。
    それらのディレクトリー内にあるファイルをプロセスIDとして収集する。
  3. Javaアプリケーションが終了すると、「hsperfdata_ユーザー名」の下の自分のプロセスIDのファイルを削除する。

したがって、Javaアプリケーション実行時のTMPとjps実行時のTMPが異なると、jpsはプロセス情報を収集することが出来ない。(プロセスIDが表示されない)


jstack

jstackは、スレッドダンプを表示するツール。[2009-12-12]
UNIXではJDK1.5から、WindowsではJDK1.6から提供されるようになったらしい。

Windowsの場合、Javaプログラムを実行しているコンソールで「Ctrl+Break(またはCtrl+Pause)」を押すと、そのプログラムのスレッドダンプが出力される。
UNIXの場合はJavaプログラムを実行しているコンソールで「Ctrl+\」。または「SIGQUITを送る」、つまり「kill -QUIT プロセスID」を実行するとスレッドダンプが出力される。
が、jstackは、それを行う専用のツール。

> jstack プロセスID

プロセスIDはjps辺りで調べる。

なお、「jstack -h」または「jstack -help」でヘルプが表示される。


jconsole

jconsoleは、実行中のJavaプログラムの状態を表示するツール。[2009-12-12]
このツールはGUI、すなわちウィンドウアプリ。(コンソールという名前のくせに…)

実行時オプションからCPUの使用時間、スタックの状態など、色々な情報が見られる。

JDK1.5で導入されたが、JDK1.6でさらに改善されたらしい。

> jconsole
> jconsole プロセスID

オプション無しでjconsoleを起動すると、最初に実行中のJavaアプリの一覧が表示され、そこから監視したい対象に接続することが出来る。


Java目次へ戻る / 新機能へ戻る / 技術メモへ戻る
メールの送信先:ひしだま