javaコマンド入門

# 第４章 コードを実行する

## Javaアプリケーションの種類

javaコマンドによるアプリケーションの実行について説明する前に、
Javaのアプリケーションにはどういったものがあるのかを見ていきます。

以下、Javaアプリケーションの大まかな分類です。
説明もざっくりしているので、気になった方はご自身で調べてください。

- コンソールアプリ  
PromptやTerminalなど、コンソールから対話方式で利用するアプリ。
- デスクトップアプリ  
１端末内で完結しているアプリ。GUIと言われることもある。
- Webアプリ  
Webサーバとクライアント間の通信により処理を行うアプリ。
- Androidアプリ  
Android向けのデスクトップアプリ。(ものの例えです)
- 組み込み系プログラム  
家電など、ハードウェアに直接組み込まれたプログラム。

javaコマンドでは主に、コンソールアプリやデスクトップアプリの実行を行います。

## javaコマンドの概要

javaコマンドを実行すると、Javaアプリケーションが起動します。
javaツールはまずJREを起動し、コマンドで指定されたクラスをロードします。
ロードされたクラスのmainメソッドが呼び出されることにより、mainメソッド内で呼び出される
他のクラスを順次ロードしながら、アプリケーションが実行されていきます。

mainメソッドを持つクラスの指定方法には、
クラスを直接指定する方法と、JARファイルを指定する方法があります。

### mainメソッドの規約

mainメソッドはpublicでstaticであること、引数にString型の配列を取ること、
戻り値を返さないことを満たしたメソッドである必要がある。

```java:mainメソッド
    public static void main(String[] args) {
        // 何らかの処理
    }
```

### javaコマンドの基本構成

```shell
# java [ options ] class [ argument ... ]
$ java HelloWorld "args1" "args2"
```

上記の例では、HelloWorldクラスのmainメソッドが呼び出され、mainメソッドの引数argsには
"args1"と"args2"が格納されたString型の配列が渡されます。

### クラスファイルの実行

クラスファイルの実行には、完全指定のクラス名を指定する必要があります。
上記の例ではパッケージ構成を取っていなかったため、
パッケージを指定しなくても実行できましたが、パッケージ構成をとっている場合には
パッケージを指定した完全指定でクラス名を指定する必要があります。

```shell
# カレントディレクトリは/src
# /srcをパッケージルートとし、HelloWorldが/src/com/example/app直下にある場合
$ java com.example.app.HelloWorld
```

### JARファイルの実行

JARファイルを指定する場合、JARファイルにアーカイブされたクラスファイルから
mainメソッドを持つ起動クラスを特定するため、マニフェストファイルのMain-Classヘッダを
設定する必要があります。ここら辺の詳細は、以下の記事がわかりやすかったです。

参照記事：[JARファイル入門 @hiwm0126](https://qiita.com/hiwm0126/items/1b3c008c21463d78337a)

JARファイルの起動には、JARファイルの配置先を指定します。(絶対パス、相対パスどちらも可)
また、起動クラスにJARファイルを指定する場合は-jarオプションを付与する必要があります。

```shell
# カレントディレクトリは/(ルート)
# /lib/jars/sample-app.jarを実行する
$ java -jar /lib/jars/sample-app.jar
```

## javaコマンドのオプション

### 主要なオプション

- -classpath(または-cp) <パス>  
ユーザクラスの検索先を指定する。  
複数選択時はセミコロン(Windows)、またはコロン(Unix)で区切る。
- -jar <パス>  
起動クラスにJARファイルを指定する。パスにはJARファイルの配置先を指定する。
- -version  
Javaのバージョン情報を表示する。
- -D<プロパティ名>=<値>  
Javaのシステムプロパティを設定する。設定した値は以下のように取得できる。

```shell
$ java -Dsun.boot.class.path="/sample/path" SampleApp
```
```java:SampleAppクラス
// 設定した値「/sample/path」が取得できる
System.getProperty("sun.boot.class.path");
```

### アサーション系のオプション
Javaのアサーションの有効、無効を設定するオプションです。
アサーションは、デフォルトでは無効になっています。

- -enableassertions(または-ea):<適用範囲>  
アサーションを有効にする。適用範囲の指定には、以下の種類がある。
    - <パッケージ名>...  
    指定したパッケージとそのサブパッケージで有効になる。
    - ...  
    カレントディレクトリのデフォルトパッケージ（無名パッケージ）で有効になる。
    - <クラス名>  
    指定したクラスで有効になる。
    - 引数なし  
    システムクラスを除く全てのクラスで有効になる。
- -disableassertions(または-da):<有効範囲>  
アサーションを無効にする。適用範囲の指定は、-enableassertionsオプションと同じ。
- -enablesystemassertions(または-esa)  
全てのシステムクラスのアサーションを有効にする。
- -disablesystemassertions(または-dsa)  
全てのシステムクラスのアサーションを無効にする。

### デバッグ系のオプション

- -verbose:{keyword list}  
コンマで区切られたキーワードリストにより指定された情報を通知する。  
    - class  
    クラスがロードされるタイミングで、クラスに関する情報を表示する。  
    - gc  
    ガーベジコレクションが動くたびに起動を通知する。  
    - jni  
    ネイティブメソッドの使用、Java Native Interfaceアクティビティの情報を通知する。

### HotSpot系のオプション

HotSpotとは、JVMに組み込まれている処理高速化のための技術の総称。
JITコンパイラ(実行時コンパイラ)の一種で、一定回数以上実行されたメソッドのみを
コンパイルするなど、処理最適化のための仕組みが用意されている。

HotSpotにはJava HotSpot Client VM(クライアント版)とJava HotSpot Server VM(サーバ版)の
２種類があり、それぞれ以下の特徴がある。

- クライアント版  
コンパイル対象を重要なクラス、メソッドに絞り、高速なロードを重視する。
- サーバ版  
全体的にコンパイルするのでロードは遅くなるが、最適化を重視する。

以下は、利用するHotSpotを指定するためのオプションです。

- -client  
Java HotSpot Client VMを選択して起動する。
- -server  
Java HotSpot Client VMを選択して起動する。

### ネイティブエージェントライブラリ系のオプション

Javaには、Java以外でコーディングしたプログラムを利用する仕組みがあり、
Java Virtual Machine Tool Interface(JVMTI)を介してエージェント(JVMTIのクライアント)と
やり取りすることで利用が可能となる。
このエージェントが、Java以外の言語で実装された各種ツールである。

以下のオプションは、これらのネイティブエージェントライブラリを利用するためのオプションである。

- -agentlib:<ライブラリ名>=<オプション>  
ネイティブエージェントライブラリを指定し、ロードする。
- -agentpath:<ライブラリのフルパス>=<オプション>  
フルパスでネイティブエージェントライブラリを指定し、ロードする。

## 実行

それでは、サンプルコードを実行していきます。

サンプルコードでは、Nullもしくは空文字が渡されると"NG"を、
それ以外の場合は引数の文字列を返すメソッドの処理結果を３件出力しているので、
"NG"、"NG"、"Hello World!"の３行が出力されるはずです。

```shell
# カレントディレクトリは/java-sample/srcです
$ java -cp /java-sample/lib/commons-lang3-3.10.jar:/java-sample/src com.example.app.UseCommons
# 以下、出力結果です
NG
NG
Hello World!
```

[メインページに戻る](https://qiita.com/maple_syrup/items/c0aa2eacb8f486dc52a8)