Dev Study
← 解説「java・javac・jar・javap: JDK のコマンド」に戻る

サンプルコードで身につける: java・javac・jar・javap: JDK のコマンド

解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。

1用語早見表: JDK の4つのコマンド

4つのコマンドを、一言の定義、手元での打ち方、Node で近いものの順に並べた表です。「近いもの」は位置のたとえで、当たらない点をかっこの中に添えました。、、 は、大文字小文字と点の有無だけが違う別の語です。

用語早見表(java・javac・jar・javap)表
用語 | 一言で
手元では: 何として見えるか
近いもの: Node / TypeScript で近いもの
 
javac | .java から .class を作るコンパイラ
手元では: javac Hello.java で Hello.class ができる
近いもの: tsc(javac は JDK に入っている。
tsc は npm で後から入れる)
 
java | JVM を起動して、指定したクラスの main を呼ぶ
手元では: java Hello、java -jar app.jar
近いもの: node(node にはファイル名を渡す。
java にはクラスの名前を渡す)
 
jar | .class などを JAR にまとめる。JAR の中を見る
手元では: jar --create ...、jar tf app.jar
近いもの: zip を作る道具(jar はマニフェストという
説明書きを自動で入れる点が違う。
npm pack との対応は確かめていない)
 
javap | .class の中身を、人が読める形で表示する
手元では: javap Hello.class、javap -p -c ...
近いもの: 無い(tsc が出す .js はそのまま読める)
 
JDK の bin | これらのコマンドが入っているフォルダ
手元では: JDK を入れた場所の bin/
Temurin 25.0.4.1 では30個
近いもの: 対応を確かめていない
 
JAR | .class などをまとめた zip 形式のファイル(形式の名前)
jar | その JAR を作る、中を見るコマンド(道具の名前)
.jar | JAR のファイル名に付く拡張子
手元では: jar tf app.jar の、jar がコマンドで
app.jar がファイル
近いもの: 無い

2オプション早見表: コースに出るものの意味

コースの図やラベルに出てくるオプションを、コマンドごとにまとめました。意味は 25 のツールリファレンスの説明を短くしたもので、 の(なし)と の行だけは実測です。-X、-XX、-p、-Djarmode は後のレッスンに出るので、ここでは形だけ見てください。

java・javac・jar・javap のオプション(# の行は組の見出し)表
オプション | 意味
例: 実際のコマンド行
 
# java(書式は java [オプション] クラス名 [引数])
-cp 場所 | クラスを探す場所の一覧
-classpath、--class-path とも書く
複数並べるときは : で区切る(Windows は ;)
例: java -cp out app.Main
-jar ファイル | JAR を指定して起動する
JAR の中のマニフェスト(説明書きのファイル)の
Main-Class の行に書かれたクラスが動く
このとき -cp など他の場所の指定は無視される
例: java -jar app.jar
(クラス名や JAR 名の後ろ) | java は読まない
動かすプログラムへの引数になる
例: java -jar demo.jar --server.port=8084
例: java ... PlainApp --debug
-version | 版を表示して終わる
例: java -version
-D名前=値 | システムプロパティ(名前と値の組)を設定する
例: java -cp out -Dwho=Java app.Main
-Xlog:... | JVM のログを出す
例: java -Xlog:class+load -cp out app.Main
-Xint | 機械語への変換をせず、解釈実行だけで動かす
-Xshare:... | クラスデータ共有(CDS)の使い方を決める
-Xshare:off は、共有されたクラスのデータを使わない
例: java -Xshare:off -Xlog:class+load -cp out ...
-XX:... | HotSpot の細かい調整用。変わりうる
例: -XX:AOTCache=ファイル(AOT キャッシュの場所)
-p 場所 | モジュール(部品の単位の1つ)を探す場所
--module-path とも書く。javap の -p とは別の意味
--add-modules 名前 | 追加で読み込むモジュールを指定する
例: java -p ... --add-modules spring.core,org.slf4j ...
-Djarmode=tools | -D の1例。Spring Boot の JAR に付いた
道具を、アプリの代わりに動かす指定
JAR 名の後ろの list-layers や extract は、
その道具への引数(層の一覧、中身の取り出し)
例: java -Djarmode=tools -jar demo.jar list-layers
例: java -Djarmode=tools -jar application.jar
extract --layers --destination extracted
 
# javac(引数はソースのファイル名)
-d フォルダ | .class の出力先。無ければ作られる
書かないと、ソースと同じ場所に .class が出る
例: javac -d out src/app/Main.java
-cp 場所 | コンパイルに使う .class を探す場所
-sourcepath 場所 | 使っているクラスのソースを探す場所
例: javac -d out -sourcepath src src/app/Main.java
--release 版 | その版の Java 向けの .class を作る
例: javac -d rel22 --release 22 Hello.java
-parameters | メソッドの引数の名前を .class に残す
-g:none | デバッグ用の情報を付けない
-version | javac の版を表示する
例: javac -version
-O | JDK 25 のマニュアルの一覧には無い
受け付けられたが、出力の .class は付けない場合と同じ
 
# jar(最初に、何をするかを書く)
c または --create | JAR を作る
t または --list | JAR の中のファイル名を一覧する
x または --extract | JAR からファイルを取り出す
f または --file | 扱う JAR のファイル名を、次に書く
e または --main-class | 入口のクラス名を、次に書く
(マニフェストの Main-Class の行になる)
-C フォルダ | そのフォルダに移ってから、ファイルを入れる
例: jar tf app.jar
= jar --list --file app.jar
例: jar cfe app2.jar app.Main -C out .
= jar --create --file app2.jar
--main-class app.Main -C out .
 
# javap(引数は .class のファイル名かクラスの名前)
(なし) | private 以外のフィールドとメソッドの一覧
-p | private も含めて全部
-c | メソッドごとの命令列(バイトコード)
-v | 大きさ、版の番号、定数の表などの詳しい情報
-cp 場所 | クラスを探す場所
例: javap -p -cp out lib.util.Greeter

3javac から javap まで、一巡する

2つのを でコンパイルし、 で動かし、jar でまとめ、 で動かし、javap で中を見るまでの記録です。Main.java しか渡していないのに が2つできたのは、-sourcepath src で、使っている別のクラスのソースの場所を教えたからです。 の一覧にある は、jar コマンドが自動で作った(JAR の説明書きのファイル)です。

JDK 25(Temurin 25.0.4.1)での実行から、順に抜粋(1つの実行の記録)コマンド出力
$ javac -d out -sourcepath src src/app/Main.java
 
$ find out -type f | sort
out/app/Main.class
out/lib/util/Greeter.class
 
$ java -cp out app.Main
Hello, world! sum=5
 
$ jar --create --file app.jar --main-class app.Main -C out .
 
$ jar tf app.jar
META-INF/
META-INF/MANIFEST.MF
app/
app/Main.class
lib/
lib/util/
lib/util/Greeter.class
 
$ java -jar app.jar
Hello, world! sum=5
 
$ javap -cp out lib.util.Greeter
Compiled from "Greeter.java"
public class lib.util.Greeter {
public lib.util.Greeter();
public java.lang.String greet(java.lang.String);
}

4javap のオプションなし・-p・-c・-v で、見えるものが変わる

上のコードは、小さなクラスをコンパイルして、javap をオプションなし、-p、-c の順に呼びます(private な secret は -p のときだけ出ます)。下の実物は JDK 25 での の先頭12行で、強調した major version: 69 が .class の版の番号です。ブラウザでの実行は JDK 22 なので、-c の字下げなどは JDK 25 と少し違います。

$ javap -v Hello.class の先頭12行(Temurin 25.0.4.1。日付とパスは置き換えてある。全体は65行)コマンド出力
Classfile /w/Hello.class
Last modified (date); size 401 bytes
SHA-256 checksum 10d6241194cddab9435b00d8b6141477175943693eed9d2fcca26d4a3217f10f
Compiled from "Hello.java"
public class Hello
minor version: 0
major version: 69
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #21 // Hello
super_class: #2 // java/lang/Object
interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
Java

5混同しやすいもの: 渡すのはファイル名か、クラスの名前か

javac にはファイル名を、java にはクラスの名前を渡します。無い名前を渡したときと、javac に別のクラスの場所を教えなかったときの実物です。[exit 1] は、実験用のスクリプトが足した終了コード(0 が成功、0 以外が失敗)の行で、# で始まる行は補足です。

失敗の実物(Temurin 25.0.4.1)コマンド出力
# 何を渡すか
# javac ソースのファイル名 javac Hello.java
# java クラスの名前 java Hello
# java -jar のときは JAR の名前 java -jar app.jar
# jar JAR と、入れるファイル jar tf app.jar
# javap .class のファイル名か、クラスの名前
 
# java に、無いクラスの名前を渡す
$ java Nope
Error: Could not find or load main class Nope
Caused by: java.lang.ClassNotFoundException: Nope
[exit 1]
 
# javap に、無いクラスの名前を渡す
$ javap Nope
Error: class not found: Nope
[exit 1]
 
# javac に、Main が使う Greeter の場所を教えない
$ mkdir -p out2 && javac -d out2 src/lib/util/Greeter.java && javac -d out3 src/app/Main.java
src/app/Main.java:3: error: package lib.util does not exist
import lib.util.Greeter;
^
src/app/Main.java:9: error: cannot find symbol
System.out.println(new Greeter().greet(who) + " sum=" + add(2, 3));
^
symbol: class Greeter
location: class Main
2 errors
[exit 1]
 
# 先に作った Greeter.class の場所を -cp で教えると通る
$ javac -d out3 -cp out2 src/app/Main.java

図やコードに出てくる用語(タップで説明)