VMwareでLinux仮想マシンを作成する③

前回の記事「VMwareLinux仮想マシンを作成する②」ではRHEL仮想マシンを作成しました。
今回は仮想マシンのネットワーク接続について説明していきます。

VMware Workstation Playerのネットワークアダプタ

VMware Workstation Playerではブリッジ/NAT/ホストオンリーという3種類のネットワーク接続の設定が可能です。 ネットワーク接続は以下の手順で確認ができます。
デフォルトの接続設定はNATです。

  1. VMware Workstation Playerの仮想マシンを右クリックしたメニューから「設定」をクリック
  2. 「ハードウェア」タブのデバイスネットワークアダプタ」をクリック

VMware Workstation Playerはネットワーク接続の種類に応じて自動でネットワーク設定を行います。
ホストOSにはVMware Workstation Playerインストール時に以下のネットワークアダプタが作成されています。

  • VMware Network Adapter VMnet1
  • VMware Network Adapter VMnet8

VMnet1はホストオンリー接続、VMnet8はNAT接続のときのホスト側インターフェースとして使用されます。

ネットワークアダプタの設定画面を見てわかるように、VMware Workstation Playerでは以下の5種類のネットワークを選択できます。

  • ブリッジ
  • NAT
  • ホストオンリー
  • カスタム
  • LANセグメント

上記のうち、今回はブリッジ、NAT、ホストオンリーについて説明します。
各ネットワーク接続可否を以下にまとめます。

項目    ブリッジ       NAT    ホストオンリー
ネットワークインターフェース なし VMnet8 VMnet1
ホスト→ゲスト接続
ホスト←ゲスト接続
ゲスト→外部ネットワーク接続 ×
ゲスト←外部ネットワーク接続 × ×
ゲストーゲスト接続

ブリッジ

ブリッジ接続は仮想マシンがホストのNIC(Network Interface Card)をネットワークアダプタとして扱うことで、仮想マシンが外部接続可能できるネットワーク接続です。
VMware Workstation Playerでは外部ネットワークからも仮想マシンに接続させたい場合はブリッジ接続を使用します。
ネットワーク構成のイメージ図を以下に示します。

  • ホストOSとゲストOSのIPを同一セグメントにすることで接続が可能
  • ホストマシンの物理NICを使用して直接外部と接続が可能

NAT

NAT接続はNATデバイス仮想マシンIPアドレスをホストのIPアドレスに変換することで、仮想マシンが外部接続できるネットワーク接続です。
仮想マシンが外部ネットワークに接続する場合はブリッジ接続かNAT接続を使用します。
ブリッジ接続は仮想マシンのセグメントをホストに合わせる必要があるのに対して、NAT接続は仮想マシンIPアドレスをプライベートIPアドレスで設定することが可能です。
ネットワーク構成のイメージ図を以下に示します。

# Virtual ethernet segment 8
# Added at 12/15/23 12:14:03
subnet 172.16.219.0 netmask 255.255.255.0 {     # セグメント定義
range 172.16.219.128 172.16.219.254;            # default allows up to 125 VM's
option broadcast-address 172.16.219.255;
option domain-name-servers 172.16.219.2;        # DNSサーバのIPデフォルトアドレス
option domain-name "localdomain";
option netbios-name-servers 172.16.219.2;
option routers 172.16.219.2;                    # ゲートウェイのデフォルトIPアドレス
default-lease-time 1800;
max-lease-time 7200;
}
host VMnet8 {
    hardware ethernet 00:50:56:C0:00:08;
    fixed-address 172.16.219.1;                 # VMnet8のデフォルトIPアドレス
    option domain-name-servers 0.0.0.0;
    option domain-name "";
    option routers 0.0.0.0;
}
# End

ホストオンリー

ホストオンリー接続は仮想マシンがホストとのみ接続可能なネットワーク接続です。
隔離されたネットワークを再現することになるので、たとえばスタンドアロンのシステムのOSをバージョンアップさせる必要が発生したときの検証環境として使用するなどがシチュエーションとしては考えられます。
ネットワーク構成のイメージ図は以下の通りです。

# Virtual ethernet segment 1
# Added at 12/15/23 12:14:03
subnet 172.16.198.0 netmask 255.255.255.0 {     # セグメント定義
range 172.16.198.128 172.16.198.254;            # default allows up to 125 VM's
option broadcast-address 172.16.198.255;
option domain-name-servers 172.16.198.1;
option domain-name "localdomain";
default-lease-time 1800;
max-lease-time 7200;
}
host VMnet1 {
    hardware ethernet 00:50:56:C0:00:01;
    fixed-address 172.16.198.1;                 # VMnet1のデフォルトIPアドレス
    option domain-name-servers 0.0.0.0;
    option domain-name "";
}
# End

IPアドレスの固定化

ゲストのIPアドレスDHCPにより都度変更の可能性があるため、 これを回避するためにIPアドレスを固定化しておくと便利な場合があります。
設定するIPアドレスは同一セグメント内で重複しないものから任意に選択してください。 IPアドレスを固定化する場合は、最低限IPアドレスゲートウェイDNSを設定します。

(ゲストの固定IPアドレスを設定)
# nmcli connection modify {コネクション名} ipv4.method manual ipv4.address {ゲストIPアドレス/サブネットマスク}

(ゲートウェイに仮想SWのIPアドレスを設定)
# nmcli connection modify {コネクション名} ipv4.gateway {ゲートウェイのIPアドレス}

(DNSに仮想SWのIPアドレスを設定)
# nmcli connection modify {コネクション名} ipv4.dns DNSのIPアドレス}
項目   ゲートウェイ      DNS   
ブリッジ ホストのゲートウェイ ホストのDNS
NAT NAT構成のゲートウェイ(xxx.xxx.xxx.2) NAT構成のDNS(xxx.xxx.xxx.2)
ホストオンリー 設定不要 VMnet1(xxx.xxx.xxx.1)

上記と同様にホストのネットワークアダプタVMnet1とVMnet8も同一セグメント内で任意のIPアドレスに変更可能です。

まとめ

今回はVMware Workstation Playerのネットワーク接続について説明しました。
ホスト/ゲスト/外部ネットワーク との接続の違いで適切なネットワークが存在しますので、仮想マシンの用途に応じて選択できるようになるとよいでしょう。
個人的にはホスト型の仮想マシンを本運用で使うことはあまりなく、ローカル上に検証環境として利用するケースが多いのかなという印象です。
隔離されたシチュエーションを再現する必要がないのであれば、仮想マシンをプライベートIP化できるNAT接続が利用しやすいのではないかと思います。
次回はRHELサブスクリプション適用を説明します。

VMwareでLinux仮想マシンを作成する②

前回の記事「VMwareLinux仮想マシンを作成する①」ではVMware Workstation Playerのセットアップまでを行いました。
今回はRHELのイメージをダウンロードして仮想マシンを作成します。

RHELの概要

RHELは「Red Hat Enterprise Linux」の略称で、数種類あるLinux OSのひとつです。
主に法人サーバ向けに開発されており、サポートが充実しているのが特徴です。 サポートを利用するためにはサブスクリプション契約でサポート料金を支払う必要があります。
ただし開発目的(非商用目的)の場合は、開発者用サブスクリプションを発行してもらうことで16台まで無償利用が可能となっています。 開発者用サブスクリプションの有効期間は1年です。
今回はこちらの無償利用の手順を説明していきます。

RHELダウンロード手順

RHELのイメージファイルをダウンロードする流れを説明します。
1~5の手順はRHELの開発者用サブスクリプションを既に持っている人はスキップしてください。

  1. RHELの開発者向けトップページを開きます。
  2. developers.redhat.com
  3. 画面右上の「Log in」アイコンをクリックします。
  4. 「Register for a Red Hat account」をクリックします。
  5. Red Hatのアカウント登録情報を入力します。
  6. 入力が終わったら「Create my account」をクリックします。 入力したメールアドレスへ登録確認メールが送信されます。
  7. 「Verify email for Red Hat account」の件名で登録確認メールを受信したら、メール本文の「Link to e-mail address verification」をクリックします。
  8. Red Hatアカウントでログイン後、以下のダウンロードページを開きます。
  9. developers.redhat.com
  10. 画面下にスクロールして、ダウンロードしたいバージョンのイメージファイルをダウンロードします。 今回は Red Hat Enterprise Linux 9.3 の x86_64 DVD ISOファイルをダウンロードしました。
  11. イメージファイルをダウンロードすると、開発者用サブスクリプションが発行されます。このサブスクリプションをインストールしたRHELに適用する必要があります。
  12. https://access.redhat.com/management/subscriptions
  13. ISOファイルをダウンロードできていることを確認して、ダウンロードは終了です。

RHELインストール手順

仮想マシンを作成してRHELをインストールする流れを説明します。

  1. VMware Workstation 17 Player を起動して「新規仮想マシンの作成(N)」をクリックします。
  2. インストーラディスクを選択します。 RHELダウンロード手順でダウンロードしたRHELのISOイメージを選択して「次へ」をクリックします。
  3. 簡易インストール情報を設定しますが、こちらの設定はこの後で使用しません。適当なフルネーム、ユーザ名、パスワードを設定して「次へ」をクリックします。
  4. 仮想マシン名と仮想マシンの格納パスを設定します。 仮想マシン名はMware Workstation 17 Player の仮想マシン一覧に表示される名称になります。
  5. ディスク容量を指定します。
    デフォルトは20.0GBで、後から拡張することも可能です
    仮想ディスクを単一ファイルとするか、複数ファイルに分割するかは用途とパフォーマンスを考慮して選択してください。
    設定に問題がなければ「次へ」をクリックします。
  6. 設定を確認して問題がなければ「完了」をクリックします。
    インストールが開始されます。
  7. VMware Workstation Player の画面をクリックすると仮想マシンの操作が可能になります。 方向キーで「Install Red Hat Enterprise Linux 9.3」を選択して「Enter」キーを押下します。
  8. 「日本語」を選択して「続行」をクリックします。
  9. 「インストール概要」画面では以下の3つの設定を行います。
    ・ rootパスワード
    ・ ソフトウェアの選択
    ・ インストール先
  10. 「rootパスワード」の設定画面では、rootパスワードを設定します。
    rootユーザでのSSHログインを許可したい場合は「パスワードによるroot SSHログイン」のチェックボックスにチェックを入れてください。
    rootユーザのSSHログインはセキュリティ上あまり推奨されませんが、今回は検証ということで許可しています。
  11. 「ソフトウェアの選択」の設定画面では、初期インストールするソフトウェアを選択します。
    デフォルトは「サーバー(GUI使用)」が選択されていますので、GUI操作をしたい場合は変更不要です。
    今回は最小容量の仮想マシンを作成したいので「最小限のインストール」を選択して「完了」をクリックします。
  12. 「インストール先」の設定画面はデフォルト設定のまま「完了をクリックします。
  13. 上記設定後、画面下の「インストールの開始(B)」が活性化するので、このボタンをクリックしてインストールを開始します。
  14. インストールが完了したら「システムの再起動(R)」をクリックします。
  15. 再起動完了後、ログイン画面が表示されます。
    ※「localhost logiin: 」が最下行に表示されない場合は「Enter」キーを押下してください。
  16. root ユーザでログインします。手順10で設定したrootパスワードを入力して[root@localhost ~]#のプロンプトが表示されたらログイン成功です。
    ログインできることを確認したら、RHELのインストールは完了です。
  17. RHELを終了する場合はshutdownコマンドを実行してください。
  18. # shutdown -h now

仮想マシンの確認

作成した仮想マシンVMware Workstation Player の一覧に表示されます。

また、仮想マシンのファイルはRHELインストール手順4で設定したパスに作成されます。

仮想マシンファイルは以下の構成になっています。仮想ディスクを複数ファイルに分割したため、「Red Hat Enterprise Linux 9-s001.vmdk」~「Red Hat Enterprise Linux 9-s032.vmdk」の32ファイルが存在します。

仮想マシンはフォルダごと複製することでバックアップを作成することができます。

まとめ

今回はRHEL仮想マシンを作成しました。
RHELRed Hatアカウントを作成して、開発目的であればイメージファイルをダウンロードして無償利用が可能です。イメージファイルをダウンロードすると開発者用サブスクリプションが発行されます。
次回からはWindowsホストOSとRHEL仮想マシン(ゲストOS)のネットワーク接続について説明していきます。

VMwareでLinux仮想マシンを作成する①

今回からWindows OS上でLinux OSの仮想マシンを作成する方法を説明してみます。 1回の記事では書ききれないので連載形式にします。

仮想マシンとは

仮想マシンとはひとつのコンピュータ(物理マシン)内に疑似的なコンピュータを再現したものです。
仮想マシンを動作させている基盤のコンピュータをホストといい、ホストに対して仮想マシンをゲストといいます。 ホストOS/ゲストOSの違いで仮想マシンは「ホスト型」「コンテナ型」「ハイパーバイザー型」の3つの種類に分類されます。

仮想化ソフトウェア ホストOS ゲストOS
ホスト型 あり あり
コンテナ型 あり なし
ハイパーバイザー型 なし あり

仮想マシンの概要図

この連載ではホスト型の仮想化ソフトウェアであるVMware Workstation Playerを使用して、Windows OS上でRHEL仮想マシンを作成してみます。

VMware Workstation Player

VMware Workstation Playerはホスト型の仮想ソフトウェアで商用利用でなければ無償で利用が可能です。 システム要件およびホストOS要件は以下の通りです。

システム要件

  • 2011 年以降にリリースされた 64 ビット互換 x86/AMD64 CPU*
  • 1.3 GHz 以上の CPU
  • 2 GB 以上の RAM(4 GB 以上を推奨)

一般的なホスト OS 要件

VMware Workstation Pro および Player は、次の 64 ビット Windows または Linux ホスト OS で動作します。

サポート対象のゲストOS

VMware Workstation 16 は、32 ビットおよび 64 ビットのゲスト OS をサポートしています。

インストール手順

それではVMware Workstation Playerのインストールの流れを説明します。

  1. 以下のリンクからVMware Workstation Playerのダウンロードサイトを開きます。
  2. www.vmware.com
  3. 「無償ダウンロード」をクリックします。
  4. 「バージョンの選択」のプルダウンからダウンロードしたいバージョンを選択後、「ダウンロードする」をクリックします。
  5. 「バージョンの選択」のプルダウンからダウンロードしたいマイナーバージョンを選択後、「今すぐダウンロード」をクリックします。
    今回はWindows上に仮想マシンを構築するので「VMware Workstation 17.5.0 Player for Windows 64-bit Operating Systems」をダウンロードします。
  6. VMware Workstation Playerのexeファイルを実行します。
  7. VMware Workstation Playerのインストール画面が開きます。「次へ」をクリックします。
  8. 使用許諾契約書の内容を確認し、「使用許諾契約書に同意します(A)」にチェックを入れて「次へ」をクリックします。
  9. 今回はカスタムセットアップはしないので、デフォルト設定のまま「次へ」をクリックします。
  10. デフォルト設定のまま「次へ」をクリックします。
    ※ユーザエクスペリエンス向上プログラムに情報を収集してほしくない場合はチェックを外してください。
  11. デフォルト設定のまま「次へ」をクリックします。
  12. 「インストール」をクリックして、インストールを開始します。
  13. 「完了」をクリックして、セットアップを終了します。
  14. VMware Workstation 17 Player」を実行します。
  15. 以下の画面が開くことを確認できたら、VMware Workstation Playerで仮想マシンを作成する準備は完了です。

まとめ

今回は仮想マシンについて説明しました。
仮想マシンはひとつのコンピュータ内に疑似的な物理コンピュータを再現したものです。
今回でホスト型の仮想マシンソフトウェアであるVMware Workstation Playerのセットアップできました。 次回からはRHEL仮想マシンを作成していきます。

オートボクシング機能について

今回はJavaのオートボクシング機能についてです。

オートボクシング( autoboxing )とは

オートボクシングとは、基本データ型とそれに対応するラッパークラス間の変換を自動で行う機能です。
具体的には、
  基本データ型  => ラッパークラスへ変換 : ボクシング
  ラッパークラス => 基本データ型へ変換  : アンボクシング
と言います。

初期のJavaではオートボクシング機能が備わっておらず、int(基本データ型)とそのラッパークラスであるInteger間で型変換が必要でした。

  // intからIntegerクラスに変換する
  Integer integerAA = new Integer(5);
  // Integerクラスからintに変換する
  int intB = integerAA.intValue();

しかし、オートボクシング機能が備わって型変換が不要になりました。

  // int型の値をIntegerクラスに設定する(ボクシング)
  Integer integerAA = 5;
  // Integerクラスをint型の変数に設定する(アンボクシング)
  int intB = integerAA;

ただし、オートボクシングは「基本データ型<=>そのラッパークラス」の間に限られており、例えばlongとIntegerのような場合にはエラーになります。

  long lngC = 5;
  Integer integerAA = lng5;  // エラー:「型の不一致longからInteger型には変換できません」

 

オートボクシングの活用

このオートボクシング機能を活用することで、コレクションクラス(例: ArrayList)の扱いが非常に簡単になります。
理由としてはコレクションクラスでは基本データ型を直接扱えません。
その為、コレクションであるArrayListに追加する際には、intをInteger型に変換する必要があります。

  // オートボクシングを考慮しない実装例
  List<Integer> alstCast = new ArrayList<>();
  alstCast.add(new Integer(100));
  alstCast.add(new Integer(200));
  int intCast1 = alstCast.get(0).intValue();
  int intCast2 = alstCast.get(1).intValue();

上記のようなコードはエラーにはなりませんが、addする時もgetする時もコードが煩雑です。
一方で、オートボクシングを活用することでコードがシンプルになります。

  // オートボクシングを活用した実装例
  List<Integer> alistBox = new ArrayList<>();
  alistBox.add(100);  // ボクシング
  alistBox.add(200);
  int intBox1 = alistBox.get(0);  // アンボクシング 
  int intBox2 = alistBox.get(1); 

比較に注意

比較の話をする前に、まずは四則演算での計算を見ていきます。

以下のようなintとIntegerを足し算する場合、Integerがintにアンボクシングされ、結果として300が表示されます。

  int intA = 100;
  Integer integerBB = 200;

  System.out.println(intA + integerBB);  // 結果:300

ちょっと面白いのは以下の例です。

  Integer integerCC = 400;
  Integer integerDD = 300;

  System.out.println(integerCC + integerDD);  // 結果:700

上記ではIntegerクラスしか使用していませんが、足し算するために自動的にint型へアンボクシングされ、結果が700となってます。
 
このオートボクシングにより、ラッパークラスは基本データ型のように扱えるように見えますが、比較する際は注意が必要です。
例えば以下の場合、Integerがアンボクシングされ、intの100と比較されます。
そのため、実行すると「同じ」と表示されます。

  int intE = 100;
  Integer integerFF = 100;

  if (intE == integerFF) {
    System.out.println("同じ");  // こちらが出力される
  } else {
    System.out.println("違う"); 
  }

では、IntegerとIntegerの比較の場合はどうなるでしょう?
ポイントはInteger同士の比較の場合はオートボクシングは行われず、オブジェクト同士の比較となるということです。

  Integer integerGG = 100;
  Integer integerHH = 100;
  Integer integerII = new Integer(100);
  
  // 比較の危険性を説明する 例1
  if (integerGG == integerHH) {
    System.out.println("同じ");  // こちらが出力される
  } else {
    System.out.println("違う"); 
  }

  // 比較の危険性を説明する 例2
  if (integerGG == integerII) {
    System.out.println("同じ"); 
  } else {
    System.out.println("違う");  // こちらが出力される
  }

例1のintegerHHと例2のintegerIIの違いは「100」をそのまま代入(ボクシング)しているか、「new」を使って明示的にInteger型を生成しているかだけです。
どちらも同じ結果になりそうですが、 、例1は「同じ」、例2は「違う」と表示されます。
 
なぜこうなるのかを説明する前にもう一つ例を示します。

  Integer integerJJ = 128;
  Integer integerKK = 128;
  // 比較の危険性を説明する 例3
  if (integerJJ == integerKK) {
    System.out.println("同じ"); 
  } else {
    System.out.println("違う");  // こちらが出力される
  }

例3は「new」は使っておらず、代入する値が128になっただけです。
となると、先ほどの結果から考えると「同じ」となりそうですが、出力結果は「違う」となります。
 
【なぜこうなるのか】
まず大前提として、Integer同士を「==」で比較した場合、「同じオブジェクトであるかどうか」を判定することとなります。
この前提で考えれば、どれも別々のオブジェクトとなりそうなので、全部「違う」という結果になりそうなものです。
しかし、Javaの仕様を確認してみると、Integerにはキャッシュ機能があり、「-128~127」の範囲のインスタンスが用意されています。
この範囲のInteger型の変数が宣言された場合、新たなインスタンスは生成せず、キャッシュされているインスタンスを使用します。
そのため、例1のように100同士だと「同じ」となります。
反対に例3のように128同士だと「違う」となってしまいます。
この話をさらにややこしくしているのが「new」の存在です。
「new」でInteger型の変数を宣言した場合は、必ず新たなインスタンスを生成するという仕様になっています。
そのため、例2のように「-128~127」の範囲であっても「違う」となってしまうのです。
 
ラッパークラスを比較する場合、オブジェクトを比較するequalsメソッドを使いましょう。

  Integer integerJJ = 128;
  Integer integerKK = 128;
  if (integerJJ.equals(integerKK)) {
    System.out.println("同じ"); // こちらが出力される
  } else {
    System.out.println("違う"); 
  }

頼りすぎは禁物

オートボクシングによってコレクションクラスやIntegerクラスなど、非常に使いやすいくなりました。
 
しかし、オートボクシングは便利ですが、パフォーマンスに影響を及ぼすことがあります。
以下の例では、計算時にオートボクシングが行われるため、性能に悪い影響を与えます。

Integer num = 1;
for (int i = 0; i <= 1000000; i++) {
    num++;
}

また、ラッパークラスはnullが入力できるため、安易に使用すると思わぬ箇所でNullPointerExceptionとなるかもしれません。

Integer num = null;
// 様々な処理
int numInt = num; // NullpointerException

Integerなどラッパークラスを基本データ型ように使いたくなってしまいますが、ラッパークラスと基本データ型は別物であることを意識し、正しく使えるようにしましょう。

hostsによる名前解決

IPアドレスドメイン

インターネット上の通信はIP(Internet Protocol)アドレスで通信相手を指定しています。 IPアドレスは32bitのIPv4アドレスと128bitのIPv6アドレスがありますが、いずれにしても人間が覚えることは困難です。 このようなIPアドレスを人間が覚えやすい文字列に変換したのがドメイン名です。

ネットワークにおいてドメイン名とIPアドレスを変換することを名前解決と呼びます。

名前解決は一般的にネットワーク上に名前解決機能を提供するDNS(Domain Name System)サーバが構築されて、そのサーバに対してドメイン名で名前解決問い合わせを行うと、IPアドレスを取得できます。 ただ今回はローカルでできる名前解決の仕組みとしてhostsについて説明をしてみます。

hostsとは

hostsはIPアドレスドメイン名の関連付けを記述したファイルです。 hostsに名前解決情報を記述すると、OSはDNSサーバへ問い合わせをせずに、hostsの情報を参照して名前解決を行います。 各OS(WindowsLinuxMac)におけるhostsファイルの格納パスは以下の通りです。

  • WindowsC:\Windows\System32\drivers\etc\hosts
  • Mac OS/etc/hosts -> /private/etc/hosts
  • Linux OS:/etc/hosts

hostsの編集

hostsファイルはどのOSでも管理者権限で編集する必要があります。 WindowsLinuxでhostsを管理者権限で編集する手順を説明します。

Macでもhostsの編集は可能ですが、筆者がMac環境を持たないため割愛します。

Windowsの場合
  1. 「メモ帳」を「管理者として実行」で起動する
  2. 「ファイル」→「開く」を選択する
  3. 「C:\Windows\System32\drivers\etc\hosts」を開く
  4. 名前解決情報を入力
  5. IPアドレス ドメイン名
  6. 上書き保存
Linuxの場合
  1. /etc/hostsを開く
  2. $ sudo vi /etc/hosts
  3. 名前解決情報を入力
  4. IPアドレス ドメイン名
  5. 保存

hosts活用例

前述のとおり一般的にはDNSサーバへ名前解決問い合わせを行うため、hostsは日常的に使用するものではありません。 それではどういうときにhostsが活用されるかというと、例えばサーバ移行の場面があてはまります。

例として、IP10.10.10.10の稼働中サーバをIP192.168.10.10の新サーバに移行するケースを考えてみます。各サーバは共通のドメインexample.comをもちます。

ドメインexample.comを宛先にサーバへ接続をしようとするとDNSサーバが名前解決をして稼働中サーバのIP 10.10.10.10に接続をします。

DNSサーバによる名前解決のルート

こうなるとドメイン指定では新サーバへアクセスできなくなってしまいますが、hostsでexample.comを新サーバのIP192.168.10.10と関連付けることで、ドメイン指定でも新サーバに接続することが可能になります。

hostsによる名前解決のルート

これによって移行前の新サーバに対するドメイン名を使用した動作確認を行うことができます。

まとめ

hostsのポイントは以下になります。

  • hostsはDNSよりも優先される名前解決の仕組み
  • サーバ移行などで暫定的にドメインの向き先を変更したい場合で有効

hostsは安易に変更すると想定した通信ができなくなるため危険なものですが、そのことを理解したうえで有用な場面に出会ったら活用を検討してみてください。

おまけ1:WindowsのhostsとDNSの優先順位

hostsとDNSの優先順位について説明をしましたが、WindowsではもうひとつDNSゾルバキャッシュについても知っておくとよいと思います。 DNSゾルバキャッシュは以前に名前解決した情報をキャッシュに登録しておき、次に同じドメインへ接続するときにそのキャッシュ情報をもとに名前解決をすることができます。 これを踏まえるとWindowsの名前解決の優先順位は以下の通りです。

  1. DNSゾルバキャッシュ
  2. hosts
  3. DNSサーバ

hostsを変更しても名前解決に反映されない場合は、DNSゾルバキャッシュを参照している可能性があります。 DNSゾルバキャッシュはコマンドプロンプトから以下を実行することでリフレッシュできます。

C:¥>ipconfig /flushdns

おまけ2:LinuxのhostsとDNSの優先順位

hostsの名前解決はDNSよりも優先されると記載しましたが、Linuxでの優先順位は固定ではなく、 名前解決の優先順位は/etc/nsswitch.confで定義されています。 /etc/nsswitch.confの名前解決の優先順位はデフォルトでは以下のように記述されます。

hosts: files dns

hosts: の後ろに名前解決の参照先が記載されます。filesはhosts、dnsDNSサーバです。左に記述された方を優先して参照し、名前解決を行います。

ArrayListについて

今回は JavaArrayList に焦点を当ててみたいと思います。
ArrayList は配列のようなものですが、配列とは異なり、初期化時に長さを指定しなくても良い、後から自由に長さを変更できる便利なクラスです。
 
まず、配列の例を見てみましょう。

String array1[] = new String[2]; // 要素数2の配列を宣言
array1[0] = "りんご";
array1[1] = "いちご";
array1[2] = "みかん"; // 3個目の要素は設定できない(例外が発生する)

 
そして、ArrayList の例を見てみましょう。

List array2 = new ArrayList(); // 宣言時に要素数の指定は不要
array2.add("りんご");
array2.add("いちご");
array2.add("みかん"); // 好きなだけ追加可能

あらかじめ扱う要素数が決まっている場合は配列でも十分ですが、要素数が不明確な場合、ArrayList は非常に便利です。
実際の実務では、多くの場面で「要素数が不明確な場合」がほとんどです。
 
ただし、ArrayList をそのまま使用すると、いくつかの不便な点があります。
例えば、以下のコードはコンパイルは正常に終了しますが、実行時に
 「(String) array1.get(0)」
の箇所で例外が発生します。

List array3 = new ArrayList();
array3.add(1);  // 文字列ではなく、数値型を設定してしまった
String strItem = (String)array3.get(0);

 
実行時のエラーメッセージは次の通りです。

java.lang.ClassCastException:java.lang.Integer cannot be cast to java.lang.String

サンプルコードの記述ではArrayListの引数はObject型となっています。
そのため、どんな型でもaddできてしまいます。
今回の例では、文字列型の「"1"」をaddするつもりで、誤って数値型の「1」をaddしてしまいました。
しかし、引数の型はObject型なので、エラーにはなりません。
その後、getする際に文字列型に型変換を行っているため、実行時例外となってしまいました。
 
この不具合の原因の特定は意外と大変です。
get の部分で例外が発生していますが、真の原因は add している箇所にあります。
今回のサンプルはたった4行しかありませんが、コードが複雑になるにつれ、add する部分と get する部分は離れていき、原因特定が難しくなります。
 
そこで、「ジェネリクス(Generics)」の登場です。
ジェネリクスArrayList 専用の機能ではなく、もっと汎用的な概念ですが、今回は ArrayList の使い方を改善する方法に焦点を当てて説明します。

List<型> 変数名 = new ArrayList<型>();

List<型> 変数名 = new ArrayList<>(); // java 7以降は省略が可能

ジェネリクスを使用した ArrayList の宣言方法はこのようになります。
クラスの後に"<"と">"で囲み、型を指定できます。
この型指定部分は「型パラメータ」と呼ばれます。
型パラメータを指定することで、ArrayList で扱う要素の型を特定できます。
 
これによってどう変わるのか、先ほどの例で説明します。

List<String> array4 = new ArrayList<>();
array4.add(1);  // String 型の引数のみを受け付ける

上記の例では array4 は「String を扱う ArrayList」として宣言され、その結果、 array4.add(1) はビルド時にエラーとなります。
 
エラーメッセージ

型 ArrayList<String> のメソッド add(int, String) は引数 (int) に適用できません

これにより、コーディングミスを早期に発見できます。
また、型パラメータを指定しない場合、get メソッドの戻り値は Object 型となり、キャストが必要です。
しかし、型パラメータを指定すると、戻り値も指定した型となり、型変換が不要になります。(地味に便利です)
 
型パラメータ指定あり

List<String> array5 = new ArrayList<>();
array5.add("1");
String strGenItem = array5.get(0); // getの戻り値はString型になる

型パラメータ指定なし

List array6 = new ArrayList();
array6.add("1");
// getの戻り値はObject型なのでStringにキャストが必要
String strItem = (String)array6.get(0);

型パラメータを指定するということはコードの簡潔さと可読性を向上させます。
ArrayList を含むコレクションクラスを使用する際には、型パラメータを活用してコードの安全性、利便性、保守性を向上させましょう。

Java開発者のためのJavadocハンドブック

プログラムのコードを書くのは一つのステップですが、そのコードが他者に理解され、効果的に使用されるためには、適切な説明が不可欠です。
JavaプログラムにはJavadocというコードを文書化するためのツールがあります。
本記事では、Javadocの重要性や利点、使用方法について記載していきます。
 

Javadoc(ジャバドック)とは?

Javadocは、Javaプログラムのコードにコメントを追加するツールです。
メソッド、クラス、およびフィールドにコメントを追加することで、そのコードの目的や機能を明確に説明します。
これにより、他の開発者がコードを理解しやすくなり、プロジェクトで一緒に作業するのも楽になります。
また、Javadocコマンドを使用することで、追加したコメントからAPI文書を自動的に生成し、使用方法を提供することができます。
※今回はJavadocコマンドの説明は含みません。

公式:JavaDoc Guide(JavaSE/21)
docs.oracle.com  

Javadocの基本

Javadocの基本は以下の通りです。

  • /** ~ */ の間に説明を記載
  • クラス、定数、メソッドがコメントを記載する対象
  • パラメータや返却値、作成者などの情報を@(アノテーション)を使用し、表現することができる
  • コメントのフォーマットでHTMLタグを使用する
  • その他にも便利なJavadocタグが存在する

下記がJavadocを記載したソースの例です。

/**
 * Javadocのサンプルクラス
 * @author 作成者
 * @version 1.0
 */
public class JavadocSample {
    
    /** 半角スペース */
    private String SPACE_HALF = " ";
    
    /**
    * 社員IDと社員名から、社員IDと苗字を結合したものを返却<br>
    * 社員名がnullの場合は空文字を返却
    *
    * @param empId 社員ID
    * @param empNm 社員名(半角スペースで結合された苗字と名前)
    * @return 社員IDと苗字を結合した文字列、または空文字
    */
    public String joinEmpIdWithEmpLastName(int empId, String empNm) {
        if(empNm == null) {
            return "";
        }
        String[] empNmArray = empNm.split(SPACE_HALF);
        return empId + (empNmArray.length > 0 ? empNmArray[0] : "");
    }
}

 

Javadocの重要性

Javadocはチーム開発を行う上で非常に強力なツールです。
クラスやメソッドの使用方法が記載されたJavadocの有無で、開発や保守のスピードが大幅に変わります。

具体的には以下の例で説明します。

    // Javadocあり
    /**
    * 契約書の条件と指定された住所コードから、条件に合う社員の一覧を返却
    * <ul>
    * <li>・契約Noから契約テーブルを検索し、該当の契約データを取得</li>
    * <li>・契約データに記載している条件で、入力済みのものを抽出</li>
    * <li>・都道府県コードと契約データの検索条件を基に、該当の社員一覧を取得返却する</li>
    * </ul>
    * 
    * @param contractNum 契約番号
    * @param addressCd 住所コード
    * @return マッチング対象の一覧
    */
    public List<MEmployee> selectMatchingEmployeeList(String contractNum, String addressCd) {
        // 契約情報を取得
        // 契約情報から条件を抽出
        // 社員情報を返却
    }


    // Javadocなし
    public List<MEmployee> selectMatchingEmployeeList(String contractNum, String addressCd) {
        // 契約情報を取得
        // 契約情報から条件を抽出
        // 社員情報を返却
    }

Javadocがある場合、引数に対する返却値が一目でわかります。

Javadocがない場合、引数が理解しにくい場合があり、呼び出し元も含めてソースコードを順に見ていかなければなりません。
さらに、このメソッドが別の処理を呼び出し、その処理がさらに別の処理を呼び出すと、一つのメソッドを理解するのが難しくなります。

上記の例を見るだけで、Javadocの記載が開発や保守にとっていかに重要かが理解できると思います。

Javadocの記載方法

Javadocには記載のルールがあります。
記載する際に気を付けなければいけないのは、他の開発者が見て理解できるように書くということです。
ここからは実際に開発の現場でよく見かけるJavadocの例をご紹介したいと思います。

クラスの説明:
/**
 * Javadocのサンプルクラス<br>
 * Javadocの理解を深め、成長につなげる
 * 
 * @author 作成者
 * @version 1.0
 */
public class JavadocSample {
}

まずクラスのJavadocでは初めにクラスの目的を記載します。
クラスの役割や目的を簡潔に書くのがポイントです。

 * Javadocのサンプルクラス<br>
 * Javadocの理解を深め、成長につなげる

次に作成者やバージョンを記載します。
作成者やバージョンは、プロジェクトによっては記載しない場合もあります。

 * @author 作成者
 * @version 1.0
メソッドの説明:
   /**
    * メソッドの概要<br>
    * どんな処理をするのか記載
    *
    * @param num どんな値
    * @param str どんな値
    * @return 何を返却するのか
    */
    public String javadocSample(int num, String str) {
        return num + str;
    }

まずクラスのJavadocではクラスの目的を記載します。
クラスの役割や目的を簡潔に書くのがポイントです。

 * Javadocのサンプルクラス<br>
 * Javadocの理解を深め、成長につなげる

次に製作者、バージョンを記載します。
この部分は記載が無いする現場も存在します。

 * @author 作成者
 * @version 1.0
定数の説明:
   /**
    * ほげほげ
    */
    private String HOGE_HOGE = "";

    /** ほげほげ */
    private String HOGE_HOGE = "";

定数名については上記の通り、値の説明を記載します。

HTMLタグ:

Javadocで記載したコメントが長くなり、見づらくなることはありませんか?

   /**
    * この処理はJavadocの説明用のメソッドです。
    * どうしても処理を書きたいので記載しています
    * 1.処理は特に記載していない
    * 2.処理が存在するメソッドをイメージしてもらいたい
    */
    public void javadocSample() {
    }

このようなコメントが書かれている場合、EclipseIDE)などでは次のように表示されます。

この表示ではどこで区切りがあるのか、どの部分が実際の処理を表しているのかが一目でわかりません。
このような場合、Javadoc内でHTMLタグを使用してフォーマットを行うことができます。

   /**
    * この処理はJavadocの説明用のメソッドです。<br>
    * どうしても処理を書きたいので記載しています
    * <ol>
    * <li>処理は特に記載していない</li>
    * <li>処理が存在するメソッドをイメージしてもらいたい</li>
    * </ol>
    */
    public void javadocSample() {
    }

フォーマット後の表示は以下の通りです。

このようにすることで処理の内容がわかりやすくなります。
JavadocではHTMLタグを使用してフォーマットを行うことができ、その中でもよく使用されるものには次のものがあります。

  • <br>タグ・・・改行
  • <p>タグ・・・段落を付けたい
  • <ul><ol><li>タグ・・・箇条書き、番号付きリスト
  • <b><strong>タグ・・・強調

その他に<a>タグなどもありますが、あまり使用されることはありません。
<html>や<head>などは使用するとJavadocの構造が壊れる可能性があるので注意が必要です。

Javadocタグ:

HTMLタグとは別に、Javadoc内で使用できるタグも存在します。
よく使用されるタグとその内容は以下の通りです。

  • @paramタグ:引数の説明
@param 引数 引数の説明

メソッドの引数に関する説明を記述します。
引数の順番通りにすべての引数について説明します。
引数が何を表しているかを説明する際、単に英単語を翻訳するのではなく、その意味を説明します。

  • @returnタグ:返却値の説明
@return 返却値

返却される値に関する説明を記述します。
たとえば、booleanの場合は「true: チェック成功、false: チェックエラー」といった書き方をすることで、返却値の状態も伝わります。
詳細でわかりやすい説明が大切です。

  • @throwsタグ:例外の説明
@throws Exception Exceptionの説明

メソッドがthrowする例外をすべて記述します。 例外にラッパークラスを指定している場合、例外の説明まで記述するかはプロジェクトによって異なります。

その他にも、@author(開発者、作成者)、@version(バージョン)、@see(関連事項として参照の追加)、{@link}(インラインのリンクを作成)、{@inheritDoc}(@Overrideなどで継承している場合、継承クラスのJavadocを参照)などが利用できます。

一覧(JavaSE/21)
docs.oracle.com  

まとめ

長文となりましたが、私が最低限気を付けているポイントは以下の通りです。

  • 説明はわかりやすく、わかりやすい形で表現する
  • クラス、メソッド、定数に対するコメントは必須である
  • @param、@return、@throwsの情報は漏れなく記載する

フォーマットであれば<br>だけでも十分であり、自分が知らないタグを調べてまで無理に使う必要はないと思います。
綺麗に見せたい、かっこよく書きたいとか考えるかもしれませんが、何よりも優先すべきは他の人が理解できるか?というポイントでそれが満たせればJavadocとして正しい記載だと思います。

簡単ではありますが、以上がJavadocの説明でした。
Javadocコマンドについては機会があれば追加していきます。