S-JIS[2003-07-06/2024-03-22] 変更履歴

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()で出力したメッセージはどこにも出ない。


単一ファイルソースコードの実行

Java11から、1ファイルのみで構成された(publicクラスしか無い)ソースコード(Single-File Source-Code Program)は(コンパイルせずに)直接javaコマンドで実行できるようになった。[2018-10-01]

Hello.java:

public class Hello {
	public static void main(String... args) {
		System.out.println("hello");
	}
}
> java Hello.java

※ソースファイル内に他クラスが含まれていて、それを呼んでいると駄目。(通常のソースコードでは、publicでないクラスを同じソースファイルに含めることが出来る)


複数ファイルソースコードの実行

Java22から、複数ファイルのソースコード(Multi-File Source-Code Programs)の場合でもjavaコマンドで実行できるようになった。[2024-03-22]

ソースファイル内に「他のソースファイルにあるクラス」が含まれている場合、それも一緒にコンパイルされる。


パッケージ宣言の無い複数ファイルソースコードの例

multi/MultiExample.java:
public class MultiExample {
    public static void main(String... args) {
        var sub = new MultiSub();
        sub.execute();
    }
}
multi/MultiSub.java:
public class MultiSub {
    public void execute() {
        System.out.println("MultiSub.execute");
    }
}
> cd multi
> java MultiExample.java

パッケージ宣言がある複数ファイルソースコードの例

パッケージ宣言がある場合、ソースファイルから直接実行するには、ソースファイルもその構成に沿ったディレクトリーに配置されている必要がある。
(javacでコンパイルする場合は、ソースファイルは必ずしもパッケージ宣言に沿ったディレクトリーに置かれている必要は無いのだが、javaコマンドで直接実行する場合は、パッケージ宣言とソースファイルのディレクトリー構成が一致していなければならない)

multi2/com/example/MultiExample.java:
package com.example;

import com.example.sub.*;

public class MultiExample {
    public static void main(String... args) {
        var sub = new MultiSub();
        sub.execute();
    }
}
multi2/com/example/sub/MultiSub.java:
package com.example.sub;

public class MultiSub {
    public void execute() {
        System.out.println("MultiSub.execute");
    }
}
> cd multi2
> java com/example/MultiExample.java

なお、実行開始するjavaファイルと同じ場所にExampleSub.javaがあると、import文よりそのファイルが優先される。
このとき、そのファイルのパッケージ宣言がディレクトリー構成と一致していないと、コンパイルエラーになる。


クラスパスを指定する例

大規模なアプリケーションになってくると、クラスを複数の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
--release バージョン Java9以降。-sourceおよび-targetを同時に指定するのと同じ。
ただし、バージョンの指定方法は6, 7, 8等。(1.6や1.7という書き方は出来ない)
2017-09-22
-parameters メソッド(やコンストラクター)の引数名をclassファイルに保持する。JDK1.8以降。
Paramerters#getName()
2014-03-20
-g デバッグ情報(ローカル変数の名前とか)をclassファイルに含める。 2020-03-21
-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のバージョンを表示する。
Java8までは標準エラーに出力されていたが、Java9で標準出力に出力されるようになった。
2017-09-22
--version Java9以降。-versionと同じ。 2017-09-22
-verbose 使用するクラス等の詳細情報を表示する。 2010-01-10
-Xlint 推奨の警告を有効にする。細かいエラーチェックを行い、警告を出してくれる。→使用例
ソース上で警告を抑止する方法
2007-06-12

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


-sourceと-targetの関係

-source-targetを省略した場合は、コンパイラー(javac)のバージョンに応じたバージョンになる。[2008-07-16]
(Java9で、-sourceと-targetを同時に指定できる--releaseが追加になった。[2017-09-22]
-sourceと-targetの組み合わせの例

-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のバージョン(1.4とか1.6とか)を標準出力に表示して終了する。(Java9以降) 2017-09-22
-version:バージョン 実行するJavaVMのバージョンを指定する。Java9で廃止になった。 2017-09-22
-showversion 実行されるJavaVMのバージョン(1.4とか1.6とか)を標準エラーに表示して続行する 2010-01-09
--show-version 実行されるJavaVMのバージョン(1.4とか1.6とか)を標準出力に表示して続行する。(Java9以降) 2017-09-22
-cp クラスパス;
-classpath クラスパス;
--class-path
クラスパス;
クラスパス(CLASSPATH)を指定する。
実行時に使用するクラスの在る、ディレクトリーjarファイル
パス区切り(Windowsの場合はセミコロン「;」、UNIXならコロン「:」)で複数指定できる。
JDK1.6では、クラスパスワイルドカード「*」が使えるようになった。
ここで指定されたクラスパスはシステムプロパティーjava.class.pathで取得できる。
Java9から「--class-path」でも指定できるようになった。
2017-09-22
-jar 実行可能jarファイル 実行可能jarファイルを実行する。 2009-01-15
-client クライアントのVMで実行(デフォルト)
(Java8からは-serverがデフォルトになった)
2020-11-16
-server サーバーのVMで実行(メモリーを大量に使う代わりに速くなる)
Java9で廃止になった。
-serverオプションの意味→阪田 浩一さんのJavaコードが速く実行される秘密 - JITコンパイラ入門(JJUG CCC 2020 Fall講演資料)
2020-11-16
-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
-p モジュールパス;
--module-path モジュールパス;
モジュールのディレクトリーを指定する。(Java9以降) 2017-09-22
--upgrade-module-path モジュールパス;   2017-09-22
--add-modules モジュール名,   2017-09-22
--list-modules 参照可能なモジュールの一覧を表示する。(Java9以降) 2017-09-22
-d モジュール名
--describe-module モジュール名
モジュールの説明を表示する。(Java9以降) 2017-09-22
--dry-run JavaVMを作成してメインクラスをロードするが、実行はしない。検証用。(Java9以降) 2017-09-22
--validate-modules モジュール(の競合やエラー)を検証する。(Java9以降) 2017-09-22
-XX:+ShowCodeDetailsInExceptionMessages NullPointerExceptionの詳細メッセージが出るようになる。(Java14)
(Java15ではこれを付けなくても詳細メッセージが表示される。)
2020-09-29
オプション 説明
-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アプリケーション起動ツール


実行するバージョンの指定

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

> 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

クラスファイル情報

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

>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クラスファイル逆アセンブラ
package-info.classのアノテーションを確認する例


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目次へ戻る / 新機能へ戻る / 技術メモへ戻る
メールの送信先:ひしだま