ITお絵かき修行

3歩歩いても忘れないために

Upgrade Java SE 7 to Java SE 8 OCP Programmer(1Z0-810)対策 第一章 ラムダ式(1)

Upgrade Java SE 7 to Java SE 8 OCP Programmer(1Z0-810)を受けるための勉強メモ。
下記サイトが詳しそうな雰囲気だったので訳しながら追ってゆく。

■注意
全文が意訳です。正確な情報は下記リンクより一次情報を参照してください。

■お世話になる試験対策っぽいページ
java.boot.by

githubにも別の対策サイトがあったので紹介
rahulsh1.github.io


■試験
Upgrade Java SE 7 to Java SE 8 OCP Programmer | Oracle Certification Exam

1.1. ネストしたクラス、静的クラス、ローカル・クラス、無名クラスなど、Javaの内部クラスを使用する

Javaでは4種類の内部クラスを実装することができる。下記に名称と実装例を示す。

staticな内部クラスコンパイルが通るよう修正済

public class Outer {
	static class Inner {
		void doIt() {
			System.out.print("Static nested class reference is: " + this);
		}
	}

	public static void main(String[] args) {
		Outer.Inner n = new Outer.Inner();
		n.doIt();
	}
}


●標準出力

Static nested class reference is: chap1.stat.Outer$Inner@2a139a55

内部クラスと似ているが、静的クラスとして宣言している。
エンクロージングクラスのインスタンスに依存しない。エンクロージングクラスのインスタンスのstaticメソッドとフィールドへのみアクセスすることができる。
「利用シーン」
・エンクロージングクラスのインスタンスと分離したい場合
・エンクロージングクラスのインスタンスより生存期間が長い場合


内部クラス(インナークラス)
内部クラスは明示的なインスタンスとして生成する。(メンバ変数として外部のクラス内で宣言される。)
内部クラスはエンクロージングクラスと内部クラスの全てのメソッド、フィールド、エンクロージングインスタンスのthisによる参照にアクセスすることができる。

public class Outer {

    private int secretVar = 1;

    public void makeInner() {
        Inner in = new Inner();
        in.seeOuter();
    }

    class Inner {
        public void seeOuter() {
            System.out.println("Outer 'secretVar' is " + secretVar);
            System.out.println("Inner class reference is " + this);
            System.out.print("Outer class reference is " + Outer.this);
        }
    }

    public static void main(String... args) {
        Inner i = new Outer().new Inner();
        i.seeOuter();
    }
}


●標準出力

Outer 'secretVar' is 1
Inner class reference is chap1.inner.Outer$Inner@2a139a55
Outer class reference is chap1.inner.Outer@15db9742


内部クラスはエンクロージングクラスとは別のスコープで定義される。
無名クラスであることがある。(次のセクションを参照)
外部・内部クラスはお互いのメソッドを直接参照することが可能(※private宣言されてる場合でも)
OuterクラスのメソッドはInnerクラスのインスタンスを生成することでInnerクラスを使用する。
内部クラスのインスタンスはエンクロージングクラスのインスタンスとは分離されている。
内部クラスのインスタンスはエンクロージングクラスのインスタンスよりインスタンス化する必要がある。
内部クラスはエンクロージングインスタンスの生成タイミングに縛られる。(※変更不可)


ローカル内部クラス(ローカルインナークラス)
ローカル内部クラスはブロック内で定義される。ブロックは0以上の要素で構成され互いに関係する。

インスタンスメソッドにおけるローカル内部クラス」

public class Outer {

    private String x = "outer";

    public void doStuff() {

        class MyInner {
            public void seeOuter() {
                System.out.println("x is " + x);
            }
        }

        MyInner i = new MyInner();
        i.seeOuter();
    }

    public static void main(String[] args) {
        Outer o = new Outer();
        o.doStuff();
    }
}

●標準出力

x is outer


「staticメソッドにおけるローカル内部クラス」

public class Outer {

    private static String x = "static outer";

    public static void doStuff() {

        class MyInner {
            public void seeOuter() {
                System.out.println("x is " + x);
            }
        }

        MyInner i = new MyInner();
        i.seeOuter();
    }

    public static void main(String[] args) {
        Outer.doStuff();
    }
}

●標準出力

x is static outer

内部クラスはエンクロージングクラスに対するアクセスを持つ。
加えて、内部クラスはエンクロージングクラス内の変数に対するアクセスを持つ。
JavaSE7以前のバージョンでは、内部クラスはエンクロージングクラスの「定数」に対するアクセスを持っている。
内部クラスがエンクロージングクラスの変数、パラメータへアクセスする時は他の変数やパラメータで保持する。

// Java SE 7 syntax
...
public void validatePhoneNumber(String phoneNumber) {

    final int numberLength = 10;

    class PhoneNumber {
        PhoneNumber(String phoneNumber) {
            if (phoneNumber.length() > numberLength) { ... }
        }
    }
}
...

※WARNING※
Java8からは、内部クラスがエンクロージングクラスの定数または"事実上の定数"へアクセスできる。
初期化後に一度も変更されていない変数、パラメータを"事実上の定数"とする。

// Java SE 8 - successfully compiles and runs;
// Java SE 7 - compilation failure
...
public void validatePhoneNumber(String phoneNumber) {

    int numberLength = 10; // no mandatory 'final' anymore, as long as variable not modified

    class PhoneNumber {
        PhoneNumber(String phoneNumber) {
            if (phoneNumber.length() > numberLength) { ... }
        }
    }
}
...

※WARNING※
下記の例はエンクロージングクラスの変数(numberLength)の代入文が内部クラス(PhoneNumberクラス)にある場合。
変数numberLengthは定数ではないため、Javaコンパイラは「Local variables referenced from an inner class must be final or effectively final」というエラーメッセージを生成する。

// Java SE 8 - compilation failure
...
public void validatePhoneNumber(String phoneNumber) {

    int numberLength = 10;

    class PhoneNumber {

        numberLength = 12;

        PhoneNumber(String phoneNumber) {
            if (phoneNumber.length() > numberLength) { ... }
        }
    }
}
...


匿名インナークラス
GUIアプリにおけるウィジェットに対するActionリスナーを追加するときによく利用する。

public class Outer {

    public void init() {
        JButton button = new JButton();
        JLabel comp = new JLabel();

        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                comp.setText("Button has been clicked");
            }
        });
    }
}

内部クラスは匿名クラスであり、エンクロージングクラスのインスタンスの一部となる。
内部クラスの一部の箇所でインスタンス化して使用したいときによく使用される。

SomeType x = new SomeType() {     // unnamed (i.e. anonymous) inner class
    // body of class goes here
};

・SomeTypeは存在するクラスまたはインタフェースでなければならない。
・SomeTypeがクラスの場合:提供されたクラスの拡張クラス
・SomeTypeがインタフェースの場合:提供されたインタフェースの実装クラス


シャドーイング
変数やパラメータ等の箇所にて宣言した型が独特なスコープ(内部クラスやメソッドの宣言部)にて、エンクロージングクラスのスコープ内の別の宣言と同じ名前があると、
エンクロージングクラスのスコープの宣言を隠蔽する。
覆い隠された宣言部へ対して、宣言の名前単独で参照することはできない。

public class Shadow {

    public int x = 0;

    class FirstLevel {

        public int x = 1;

        void methodInFirstLevel(int x) {
            System.out.println("x = " + x);
            System.out.println("this.x = " + this.x);
            System.out.println("Shadow.this.x = " + Shadow.this.x);
        }
    }

    public static void main(String... args) {
        Shadow s = new Shadow();
        Shadow.FirstLevel fl = s.new FirstLevel();
        fl.methodInFirstLevel(2);
    }
}

●標準出力

x = 2
this.x = 1
Shadow.this.x = 0

この例では3つのxという変数が定義されている。Shadowクラスのメンバ変数、内部クラスのFirstLevelのメンバ変数、methodInFirstLevelメソッドのパラメータである。
内部クラスのFirstLevelのメンバ変数xは、methodInFirstLevelメソッドのパラメータの変数を隠蔽する。
その結果、methodInFirstLevelメソッドのパラメータの変数を使用したい時は、メソッドのパラメータを参照するようにする。
内部クラスのFirstLevelのメンバ変数を参照するには、エンクロージングクラスのインスタンスのスコープを表すthisキーワードを使用する。

System.out.println("this.x = " + this.x);


参照するメンバ変数は、所属するクラスよりもより大きなスコープに属している。
例えば、下記の代入文はmethodInFirstLevelメソッドからShadowクラスのメンバ変数へアクセスする。

System.out.println("Shadow.this.x = " + Shadow.this.x);


■参考
四種類の内部クラス - にょきにょきブログ
【改訂版】Eclipseではじめるプログラミング(17):あなたの知らない、4つのマニアックなJava文法 (1/3) - @IT
裏Javaメモ(Hishidama's Java Memo)

jol(Java Object Layout)を使ったオブジェクトのサイズ取得

jol(Java Object Layout)というOpenJDKに含まれるツールを使用して、オブジェクトのメモリサイズが取得できるらしいので試してみる。


OpenJDK: jol


■環境
Windows7 Home Premium 64bit
JDK 1.8.0_60-b27
Eclipse Luna SR1 (4.4.1)
・jol (0.4) (※jol-cli-0.4-full.jar)


■すること
jolを使用して何ができるのかを調べる。
主目的は、1処理におけるメモリ量の取得とする。
よって割とメイン所(と思われる)の機能のみ追いかける。


■クラス紹介
1.ClassLayoutクラス
jolを使用する上で基本となるクラス。クラス・クラスインスタンスのメモリ情報を取り扱う。

●処理対象特定系

通番 static 戻り値の型 メソッド 引数 メソッド概要
1 ClassLayout parseInstance Object インスタンスのメモリ情報を取得する。
2 ClassLayout parseInstance Object, Layouter インスタンスのメモリ情報を取得する。第二引数のLayouterで読み込み時の動作変更が可能
3 ClassLayout parseClass Object クラスのメモリ情報を取得する。
4 ClassLayout parseClass Object, Layouter クラスのメモリ情報を取得する。第二引数のLayouterで読み込み時の動作変更が可能

●サイズ取得系

通番 static 戻り値の型 メソッド 引数 メソッド概要
5 SortedSet< FieldLayout> fields - インスタンス内に含まれるフィールドのメモリ情報を取得する。
6 int headerSize - インスタンスのヘッダサイズ(int値)を取得する。
7 int instanceSize - インスタンスのサイズ(int値)を取得する。
8 String toPrintable - インスタンスのメモリ情報を整形して詳細情報を出力する。
9 String toString - インスタンスのメモリ情報を整形して出力する。


2.FieldLayoutクラス
フィールドのメモリ情報を取り扱う。

●サイズ取得系

通番 static 戻り値の型 メソッド 引数 メソッド概要
1 String name - フィールド名を取得する。
2 String offset - インスタンスが占めるサイズの先頭からのメモリ量を取得する。
3 int size - フィールドのサイズを取得する。
4 String typeClass - フィールドの型を取得する。
5 String toString - フィールドの詳細を取得する。


3.VMSupportクラス
JVMのメモリに関連する情報を取得する。

通番 static 戻り値の型 メソッド 引数 メソッド概要
1 String vmDetails - JVMのメモリ情報を出力する。


4.GraphLayoutクラス
インスタンス生成からGraphLayout#parseInstanceした時点までにおける、指定したインスタンスに対するメモリの状態を可視化する。

通番 static 戻り値の型 メソッド 引数 メソッド概要
1 GraphLayout parseInstance Object インスタンスのメモリ情報を取得する。
2 - toImage String 引数で指定したファイル名(~.png等)でグラフを生成する。


●HelloWorld的なやつ

package com.hhhhhskw.jol;

import java.util.SortedSet;

import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.info.FieldLayout;
import org.openjdk.jol.util.VMSupport;

public class HelloJol {

	private String HELLO_JOL_HOGE = "HOGEEEEEEEEEEEEEEEEE";
	private String HELLO_JOL_FUGA = "FUGAAAAAAAAAAAAAAAAA";


	public static void main(String[] args) {
		HelloJol hj = new HelloJol();
		System.out.println("■JVM情報■");
		System.out.println(VMSupport.vmDetails());

		System.out.println("■クラスインスタンスのメモリ情報■");
		System.out.println(ClassLayout.parseInstance(hj).instanceSize());
		System.out.println(ClassLayout.parseInstance(hj));
		System.out.println(ClassLayout.parseInstance(hj).toPrintable());

		SortedSet<FieldLayout> flSet = ClassLayout.parseInstance(hj).fields();

		flSet.stream().forEachOrdered(fl -> {
			System.out.println("■フィールドのメモリ情報■");
			System.out.println(fl.name());
			System.out.println(fl.size());
			System.out.println(fl.typeClass());
			System.out.println(fl);
		});

		System.out.println(flSet);
	}
}


●実行結果*1

■JVM情報■
WARNING: Unable to attach Serviceability Agent. You can try again with super-user privileges. Use -Djol.tryWithSudo=true to try with sudo.
WARNING: VM details, e.g. object alignment, reference size, compressed references info will be guessed.

Running 64-bit HotSpot VM.
Using compressed oop with 3-bit shift.
Using compressed klass with 3-bit shift.
Objects are 8 bytes aligned.
Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

■クラスインスタンスのメモリ情報■
24
HelloJol.HELLO_JOL_HOGE@12(4)
HelloJol.HELLO_JOL_FUGA@16(4)
size = 24

com.hhhhhskw.jol.HelloJol object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                    VALUE
      0     4        (object header)                01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                05 c0 00 f8 (00000101 11000000 00000000 11111000) (-134168571)
     12     4 String HelloJol.HELLO_JOL_HOGE        (object)
     16     4 String HelloJol.HELLO_JOL_FUGA        (object)
     20     4        (loss due to the next object alignment)
Instance size: 24 bytes (estimated, add this JAR via -javaagent: to get accurate result)
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

■フィールドのメモリ情報■
HELLO_JOL_HOGE
4
String
HelloJol.HELLO_JOL_HOGE@12(4)
■フィールドのメモリ情報■
HELLO_JOL_FUGA
4
String
HelloJol.HELLO_JOL_FUGA@16(4)
[HelloJol.HELLO_JOL_HOGE@12(4), HelloJol.HELLO_JOL_FUGA@16(4)]



【感想】
・継承関係にあるクラスのフィールドの中身までさかのぼってサイズ取得してくれるので便利。
・アプリケーション単位で特定の箇所でメモリサイズを取得する場合、インスタンスを適当に決めると、重複してサイズ取得する恐れがあるので、取得対象とするインスタンスは慎重に選ぶべき。
・VMSupport、GraphLayoutクラスを使用したサンプルは下記のソースを参照。
code-tools/jol: 4443d2696dcf /jol-samples/src/main/java/org/openjdk/jol/samples/


【参考】
[Java]オブジェクトの使用メモリを測る - Qiita

*1:「sa-jdi.jar」を入れ、VM引数に「-Djol.tryWithSudo=true」を指定することで警告を消せる可能性がある。警告は無視しても動作する。 ※手元の環境では、左記の対応を行ったうえで管理者権限で実行しても変化しなかった。。実行環境をOpenJDKにした方がよいかも。

『オブジェクトデザイン』第2章 DoubleDispatchパターン実装

下記エントリに影響を受けて、『オブジェクトデザイン』を読み始めている。kymmt90.hatenablog.com

『オブジェクトデザイン』の第2章において、DoubleDispatchパターンの実装が紹介されているが、
要点が書かれているだけで全体の実装が書かれていなかったので、実装してみた。
DoubleDispatchパターン自体は、GoFのVisitorパターンとほとんど同じものらしい。

【要件】
じゃんけん(Scissors,Paper,Stone)*1を実装する。
オブジェクト自身にオブジェクトが他のオブジェクトを負かすかどうかを判定する処理を書いておく。
→3種類のオブジェクトにじゃんけんの処理を記述するため、9通りの結果が生じることになる。

【書籍からの変更点】
『オブジェクトデザイン』の例では、「あいこ」の場合が考慮されていなかったので、
「あいこ」を表現するために、booleanからintで数値を返却するよう変更した。
変更に伴い、他のオブジェクトを負かすかどうかの判定処理を抽象クラス(※新規作成)に追い出して共通化した。

【シーケンス図】※だいぶ適当
f:id:hhhhhskw:20151101151824j:plain

【実装】github.com
■実行結果の例 (※標準出力)

自分の手 : パー
相手の手 : グー
勝敗 : 勝ち


【感想】
「操作するデータの型」「データごとの操作」に対する判定処理が消えたことで、各クラスの関心事を細かく分断することができた。
ただしインタフェースクラスに定義するメソッドの数、シグネチャが変動する可能性があるので、初期設計が難しそう。


【参考】
ダブル・ディスパッチ~ 典型的なオブジェクト指向プログラミング・イディオム ~

オブジェクトデザイン (Object Oriented SELECTION)

オブジェクトデザイン (Object Oriented SELECTION)

*1:グーはRockではなくてStoneで習った気がしたので…

PowerShellを使ってOracleJDKサイレントインストール

OracleJDKをサイレントインストールする。

【概要】
・OTNサイト(US)から取得したJDK8u45(64bit)のインストーラを使用しサイレントインストールする。*1
・ダウンロードしたインストーラは「C:\\tmp」に置く。
環境変数も設定する。
→ユーザ環境変数の「JAVA_HOME」と「PATH」にJDK実行に必要なパスを設定する。
インストーラが出力するログは「C:\tmp\JDKsetup.log」に格納する。

【実行環境】
Windows7 Home Premium 64bit
PowerShell 4.0 (※新しい関数は使っていないので、おそらくPowerShell2.0以降であれば動作する)

スクリプト

Function Download{
    $serverSourceURL = "http://download.oracle.com/otn/java/jdk/8u45-b15/jdk-8u45-windows-x64.exe"
    $localSourceURL = "C:\\tmp\\jdk-8u45-windows-x64.exe"
    Write-Host ("■インストーラ取得先URL : " + $remoteFileLocation)
    Write-Host ("■インストーラ保存先パス : " + $downloadToPath)
    
    $client = new-object System.Net.WebClient
    # ライセンスに同意する
    $cookie = "oraclelicense=accept-securebackup-cookie"
    $client.Headers.Add([System.Net.HttpRequestHeader]::Cookie, $cookie)

    Write-Host "★ダウンロード開始(しばらくお待ちください…)"
    $client.downloadFile($serverSourceURL, $localSourceURL)
    Write-Host "★ダウンロード終了"
    return
}

Function Install{
    Write-Host "★インストール開始(しばらくお待ちください…)"
    # インストーラ実行(※同期実行)
    cmd /c "start C:\tmp\jdk-8u45-windows-x64.exe /s /lang=1041 INSTALLDIR=C:\java\jdk1.8.45\ /L C:\tmp\JDKsetup.log" 
    Write-Host "★インストール終了"

    # ユーザー環境変数設定
    # PATHは末尾に付加する
    $user_path = [Environment]::GetEnvironmentVariable('PATH', 'User')
    $user_path += ';' + "C:\java\jdk1.8.45\bin\"
    [Environment]::SetEnvironmentVariable('PATH', $user_path, 'User')

    # JAVA_HOMEは更新する
    #$user_java_home = [Environment]::GetEnvironmentVariable('JAVE_HOME', 'User')
    $user_java_home = "C:\java\jdk1.8.45\"
    [Environment]::SetEnvironmentVariable('JAVA_HOME', $user_java_home, 'User')

    Write-Host ("■現在のユーザー環境変数 PATH : " + $user_path)
    Write-Host ("■現在のユーザー環境変数 JAVA_HOME : " + $user_java_home)
    return
}

# 処理開始
Write-Host "★★★Oracle JDKのダウンロード・インストール開始"

Download
Install

Write-Host "★★★Oracle JDKのダウンロード・インストール終了"
# 処理終了

■実行結果

PS C:\Windows\system32> (ファイルパス).ps1
★★★Oracle JDKのダウンロード・インストール開始
■インストーラ取得先URL : http://download.oracle.com/otn/java/jdk/8u45-b15/jdk-8u45-windows-x64.exe
■インストーラ保存先パス : C:\tmp\jdk-8u45-windows-x64.exe
★ダウンロード開始(しばらくお待ちください…)
★ダウンロード終了
★インストール開始(しばらくお待ちください…)
★インストール終了
■現在のユーザー環境変数 PATH : (既存のPATH設定値);C:\java\jdk1.8.45\bin\
■現在のユーザー環境変数 JAVA_HOME : C:\java\jdk1.8.45\
★★★Oracle JDKのダウンロード・インストール終了

■結果確認

C:\>java -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

C:\>

【備考】
インストーラを毎回取りに行くので、インストーラの有無チェックが必要。
・インストールを毎回実行するので、プログラム一覧をなめてOracle Javaの存在チェックする処理が必要。*2

【参考】
java - Downloading jdk using powershell - Stack Overflow
Microsoft WindowsのJDKのインストール

【改訂新版】 Windows PowerShell ポケットリファレンス

【改訂新版】 Windows PowerShell ポケットリファレンス

*1:PowerShellの関数のみで実行したかったが、リクエストに載せるCookieの設定方法がわからなかったので、.NETのクラスを使った。

*2:要は冪等性を作りこむ必要がある。現状のコードのまま2回実行すると、インストーラを再ダウンロードし、再インストールを実行する。

JavaでTelnetクライアント作成・RHELにTelnetサーバ導入

JavaのSocketクラスを使ってTelnet接続してみる。
ついでにTelnetサーバを立てる手順も備忘録として残す。

【すること】
Telnet接続する。
※セッションモードで端末に接続し、コマンドが打てるところまで確認する。
 NVTとしての仕様は網羅しない。

【環境】
●OS
クライアント側:Windows7 64bit
サーバ側   :Red Hat Enterprise Linux Server release 7.1 (Maipo)

Java
1.8.0_60-b27


Telnetサーバ導入】
0.はじめに
・23番ポートを空ける。
Telnetを実行するユーザはスーパーユーザである必要があるため、rootユーザで接続確認する。
 Telnetプロトコルで使用するユーザ名とパスワードは平文で流れるので注意する。
[参考] ITエンジニアの「やってはいけない」 - [セキュリティ編]運用管理にtelnetを使ってはいけない:ITpro
・スーパーサーバであるxinetdを利用してTelnetサーバを管理する。
[参考] xinetd - Wikipedia


1.インストール(※rootユーザで行う)

yum update
yum install telnet -y
yum install telnet-server -y
yum install xinetd -y ※RHELには入ってないので入れておく

2.xinetdよりTelnetサーバ有効化

vi /etc/xinetd.d/telnet

●/etc/xinetd.d/telnet

service telnet
{
        flags           = REUSE
        socket_type     = stream
        wait            = no
        user            = root
        server          = /usr/sbin/in.telnetd
        log_on_failure  += USERID
        disable         = no ←「yes」から「no」へ変更し、有効化
}

3.xinetd起動および自動起動の設定
(※xinetdを起動することによりTelnetサーバも起動する)

service xinetd start
chkconfig --add xinetd
chkconfig xinetd on

インストール手順はここまで。


Telnet接続】
Telnet接続用クラス

package hhhhhskw.com;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
 * Telnet接続用クラス
 */
public class TelnetConnector {

	private final static int DEFAULT_TELNET_PORT = 23;

	private final static byte IAC = (byte) 255;
	private final static byte DONT = (byte) 254;
	private final static byte DO = (byte) 253;
	private final static byte WONT = (byte) 252;
	private final static byte WILL = (byte) 251;

	/**
	 * NVTとしてのネゴシエーションを行う
	 * @param os
	 * @param is
	 * @throws IOException
	 */
	private void negotiation(OutputStream os, BufferedInputStream is) throws IOException {
		byte[] buff = new byte[3];
		while (true) {
			is.mark(buff.length);
			if (is.available() >= buff.length) {
				is.read(buff);
				// ネゴシエーション完了
				if (buff[0] != IAC) {
					is.reset();
					return;
				// DOコマンドに対してWONTで返答する
				} else if (buff[1] == DO) {
					buff[1] = WONT;
					os.write(buff);
				}
			}
		}
	}

	/**
	 * 実行メソッド
	 * @param host
	 * @param port
	 */
	public void execute(String host, int port) {

		Socket socket = null;
		OutputStream os = null;
		BufferedInputStream is = null;

		try {
			socket = new Socket(host, port);
			os = socket.getOutputStream();
			is = new BufferedInputStream(socket.getInputStream());

			// 23番ポートへの接続の場合ネゴシエーションを行う
			if (port == DEFAULT_TELNET_PORT) {
				negotiation(os, is);
			}

			StreamConnector stdinToSocket = new StreamConnector(System.in, os);
			StreamConnector socketToStdout = new StreamConnector(is, System.out);

			Thread input = new Thread(stdinToSocket);
			Thread output = new Thread(socketToStdout);

			input.start();
			output.start();

		} catch (IOException e) {
			e.printStackTrace(System.out);
			System.err.println("接続中に例外が発生しました");
			System.exit(1);
			// コネクションはクローズしない
			// } finally {
			// try {
			// socket.close();
			// os.close();
			// is.close();
			// } catch (IOException e) {
			// }
		}
	}

	/**
	 * ストリームの読み書きクラス
	 */
	class StreamConnector implements Runnable {

		private InputStream is = null;
		private OutputStream os = null;

		public StreamConnector(InputStream in, OutputStream out) {
			this.is = in;
			this.os = out;

		}

		@Override
		public void run() {
			byte[] buff = new byte[1024];
			try {
				while (true) {
					int n = is.read(buff);
					if (n > 0) {
						os.write(buff, 0, n);
					}
				}
			} catch (IOException e) {
				e.printStackTrace(System.out);
				System.out.println("入出力の書き込み中に例外が発生しました");
				System.exit(1);
			}
		}
	}
}

● 実行クラス

package hhhhhskw.com;

public class TelnetMain {

	/**
	 * mainメソッド
	 * @param args 第一引数:ホスト名 第二引数:ポート番号
	 */
	public static void main(String[] args) {
		String host = args[0];
		int port = Integer.parseInt(args[1]);

		TelnetConnector tc = new TelnetConnector();
		tc.execute(host, port);
	}
}

●実行方法
第一引数にサーバのホスト名(IPアドレス)、第二引数にポート番号を指定し、実行する。

java hhhhhskw.com.TelnetMain (ホスト名orIPアドレス) 23

●実行結果

Kernel 3.10.0-229.el7.x86_64 on an x86_64
(サーバ名) login: root
root
Password: (パスワード)

Last login: Sat Sep  5 07:17:35 on pts/2
[root@ip-xxx-xxx-xxx-xxx ~]# ls -al
total 104
dr-xr-x---.  4 root root  4096 Aug 31 04:23 .
dr-xr-xr-x. 18 root root  4096 Aug 30 07:59 ..
-rw-------.  1 root root  9813 Feb 25  2015 anaconda-ks.cfg
-rw-------.  1 root root  1974 Aug 31 05:34 .bash_history
-rw-r--r--.  1 root root    18 Dec 28  2013 .bash_logout
-rw-r--r--.  1 root root   176 Dec 28  2013 .bash_profile
-rw-r--r--.  1 root root   176 Dec 28  2013 .bashrc
-rw-r--r--.  1 root root   100 Dec 28  2013 .cshrc
-rw-------   1 root root 45711 Sep  5 07:18 nohup.out
drwxr-----   3 root root    18 Aug 30 08:00 .pki
-rw-r--r--   1 root root  7154 Aug 31 02:27 ps.txt
drwx------.  2 root root    28 Aug 30 07:55 .ssh
-rw-r--r--.  1 root root   129 Dec 28  2013 .tcshrc
-rw-------   1 root root   759 Aug 31 04:23 .viminfo
[root@ip-xxx-xxx-xxx-xxx ~]#


【参考URL】
http://www.kg-group.com/JavaContent/Menu/TreeView5150_16/reference/j-network/Telnet.java
Telnetプログラム IT EngineerによるIT生活/ウェブリブログ
CentOSでtelnetできるようにするまでの手順(クライアント・サーバ) | Futurismo
UJP - 技術情報(dotforward.jp)

AWS Summit Tokyo 2015 2日目【EA-08】

AWS Summit Tokyo 2015の2日目に参加した。
下記セミナーに参加したので、まとめ・感想文を書いておく。
※正確な情報・見解は後日公開される(であろう)公式資料や資料作成者のスライド等を参照のこと。

[EA-08: Enterprise Advance]AWSNGN(フレッツ・キャスト)によるハイブリット・ネットワークのメリット ~高速映像配信・教育 PF 事例~

http://www.awssummit.tokyo/session.html#EA-08

【講演概要】

AWS上のサービスをNGN(フレッツ・キャスト)という専用線を使用し、インターネットを介さずに利用するサービスの内容紹介および事例紹介
※6/5付けでサービス試用開始されている。
「プレスリリース」
「フレッツ・キャスト」経由のAWSダイレクト接続検証環境の提供開始について〜パブリッククラウドとの連携強化に向けた取り組み〜 | お知らせ・報道発表 | 企業情報 | NTT東日本

【講演内容】

0.導入

NTT東日本では、伝統的に自前のWebサービスを使用して各種コンテンツ・サービスを提供してきた。
・今回初めてAWSを利用する。

1.何故、AWSを選んだのか

・新サービス立ち上げにあたって、重視したのは「コスト」「サービス」「フレキシビリティ」の3点
→以前は「サーバ設備」や「ネットワーク」という点を重視していた。
・増え続ける動画トラフィックに柔軟に対応したい、という思いがあった。
 インターネットに占める動画トラフィック量は、2013年~2018年で倍になる、と予測されている。
 動画トラフィックの大部分はIPビデオ*1が占めており、今後もこの傾向は続くとみられる。
AWSに限らず、パブリッククラウドの選定に当たって最も重要視したのは「セキュリティ」だった。
→NTT東のお客様と社内の双方から求められた為。結果としては各種AWSのサービスの組み合わせにより担保できた。

2.フレッツ・キャストの紹介

ISPを介さずに、AWSのNWからNTT東日本のNWを通って利用者がサービスを利用することを可能とする。
・全FTTHユーザのうち、7割がNTT西・東を利用している。
・以下の3点を売りとして挙げていた。
①速度    :通信キャリアのVPNより安価で高速
②セキュリティ:回線認証(※IPSecでない)
③品質    :クローズドなNW。24時間365日対応可能。
・4KのVoDが可能となる。
→「ひかりTV 4K」等

3.サービス事例

・サービス適用例として「映像配信」「ICT教育」を挙げていた。
 ①映像配信
 ・会場と配信サーバをNGNで結び、配信はNGNかインターネット経由で行う。
 →現在は映像データをバイク便で運んでいるが、回線に置き換えられる。
 ・課題:IPv6
  AmazonVPC内ではインターナルでIPv6のアドレスを割り当てることができない点が課題。
  →リバプロを立てることで解決したとのこと。IPv6のアドレスの割り当て先としてELBを使用しなかった理由としては、セキュリティ面の都合??
  [参考]http://srad.jp/~ozuma/journal/591374/
     http://d.hatena.ne.jp/rx7/20130925/p1
 ②ICT教育
 ・ICTパッケージとして提供する。学校・学習塾がターゲット。
 →インフラから学習アプリの導入~運用まで提供する。
  「反転学習」*2にも使用できるとのこと。
 ・公教育の分野のため、個人情報の取り扱いに対する要望が強い。

●苦労した点
有識者が少なかったこと
→書籍の情報や「ドコモ・クラウドパッケージ」を活用した。

●良かった点
・IaaS部のセキュリティは外部に協力を仰いだ。(ex.スカイアーチ社)
・サーバ構成を頻繁に変更することができた。
→50~60?回は構成を変更したとのこと。

*1:IP(インターネットプロトコル)ネットワーク経由で配信する動画コンテンツを指す

*2:反転授業 - Wikipedia

AWS Summit Tokyo 2015 2日目【Day2 キーノート】

AWS Summit Tokyo 2015の2日目に参加した。
いくつかセミナーに参加したので、まとめ・感想文を書いておく。
※正確な情報・見解は後日公開される(であろう)公式資料や資料作成者のスライド等を参照のこと。
※長くなったので基調講演のまとめを前に置いた。

Day2 キーノート【同時通訳】

セッションスケジュール - AWS Summit Tokyo 2015 - クラウドで、未来を「今」に。- 2015年6月2~3日 グランドプリンスホテル新高輪にて開催

【基調講演まとめ】

1.AWSはモバイル分野・エンタープライズ分野に注力する。
AWSが言うエンタープライズ分野への注力、というのはIaaS、PaaSレイヤの提供・運用だけでなく、
 VDI環境のフルマネージメントサポート*1や、ファイル共有サービスとメールやカレンダーアプリを業務利用できるレベルでの提供、といったDaaS(※Desktop as a Service)、SaaSなどの上位レイヤのサービスも提供・運用することを指す。
 
2.AWSの各マネージドサービスは「世界で使用されているサービス」という実績がある。
AWSとしての顧客は全世界・多業種にわたる。その顧客ごとのユースケースに対して、AWSは各マネージドサービスを適用してきた実績がある。
 そのため、十分な適用・運用実績を持って顧客にアプローチをかけることが可能となっている。

【基調講演内容】

1.AWSの歴史

[内容]
・2006年からサービス開始。
・サービスの数が飛躍的に増えた。またサポートできるレイヤも増えた。
→2006年:24 2015年:516
・現在、一ヶ月におけるアクティブユーザが100万ユーザに達している。
→ここでいうアクティブユーザというのは、AWSのサービスを実運用しているレベルのユーザの数を指すらしい。

2.AWSのモバイルサービス

[概要]
AWSはモバイルデベロッパー向けのサービスに注力する。
→モバイルビジネスのモデルに沿うようなサービスを提供する、ということ。
 →インフラ*2の抽象化等。本来モバイルデベロッパーが時間をかけるべき箇所はアプリ開発であるので、その他の部分をAWSがサービスとして提供する。

[内容]
AWS LambdaとAmazon Cognitoが6/3より東京リージョンで使用可能となった。(※途中で発表された。)
AWSが提供するモバイルサービスについて、4つの観点から紹介していた。
(1)ユーザ管理
・BtoB, BtoC, MtoMなどの認証情報を扱う認証基盤として、「Amazon Cognito」を紹介した。
→「Amazon Cognito」はID認証およびデータ同期、セキュリティに関する機能を提供する認証基盤サービス。
・イベント(データ)駆動が可能となっており、データ同期を契機としてAWS Lambdaのサービスを実行する、といった使い方ができる。また、他デバイスでの認証状況をCognitoにて参照できるため、デバイス毎のアプリの使用状況の把握が可能となる。

[利用事例]
 ATARI Inc. : フィットネスアプリの認証基盤


(2)ユーザ行動分析
・「Amazon Mobile Analytics」を紹介した。
→デバイスから送られるデータをAnalyticsで受け取り、Amazon S3(データストレージ)とAmazon Redshift(分析基盤サービス)を使用し、過去分のデータとマージした結果をAnalyticsのコンソールに表示するという使い方ができる。

[利用事例]
 (※企業名は失念した) : メッセージのプッシュ基盤と組み合わせ、メッセージにおけるデバイス毎のA-Bテストに使用


(3)SNS Push
Amazon Simple Notification Service (Amazon SNS) を紹介した。
→メッセージのプッシュ基盤サービス。データ駆動が可能となっており、AWS Lambdaと組み合わせることができる。

[利用事例]
 Path Inc. : 1日5億件のメッセージを送信するプッシュ基盤サービスを構築


(4)AWS Lambda
・「AWS Lambda」では、ステートレスなイベント駆動型の処理を作成することができる。
→イベント駆動型のバックエンドサービスを作成することができるため、「インフラの抽象化」が可能となる。
Javaでの記述に対応予定。

3.Deep Dive DynamoDB

[概要]
AWSの川本さんの発表。Amazon DynamoDB紹介

[内容]
Amazon DynamoDBAmazonが社内利用するために作ったNoSQLデータベースシステム。
AWSのIaaSレイヤのサービスを扱いやすいように作られている。
・DynamoDB内に格納したデータを「DynamoDB Streams」として取り出すことができ、StreamデータをAWS Lambdaに読み込ませ、Redshift、Amazon Machine Learning(機械学習サービス)等に出力することで、サーバレスで目的のデータを取り出すことが可能となっている。

4.デベロッパ(コミュニティ)向けサービス

[概要]
AWS Community Heroes 横田さんのマネージドサービスの利用事例紹介。

[内容]
(1)スシロー
予約用モバイルアプリから待ち時間情報を収集・加工し、Amazon Machine Learningへ連携するという事例。他にも回転寿司の皿にセンサーをつけて、売れ方や廃棄を管理しているらしい。*3

(2)ガリバーインターナショナル
ユーザ認証毎?のイベント駆動でモバイルアプリにメッセージをプッシュ配信するという事例

[まとめ]
・両サービスの特徴としては、全てAWSのマネージドサービスで構築されており、EC2を一切使っていないこと。
→プログラミングが不要となる、とのこと。*4
・開発および運用をスピーディーに実行することができる。
→1ヶ月かかっていた作業が3日で完了するようになった。

5.エンタープライズモビリティ

[概要]
Gene Farrellさん(TE-10セッションの発表者)によるマネージドサービスのモバイル端末対応について
※紹介程度だった。

[内容]
・全マネージドサービスについて、モバイル端末に対応する。
→業務システムにおけるモバイルファースト
Amazon WorkDocsが東京リージョンで使用可能となるとのこと。(※途中で発表された。)
→「Amazon WorkDocs」はクラウド上でのファイル共有サービス。


基調講演はここで終了。ランチセッションに移行した。

・協賛企業一覧
f:id:hhhhhskw:20150603232559j:plain

・企業ブース(入り口入ってすぐの所)
f:id:hhhhhskw:20150603232617j:plain

*1:例としては、VDI越しに利用者が使用するユーザ企業やベンダー等が作成した業務アプリの保守を行うためのサービスを提供する等。

*2:ここではBaaSレイヤにあたる

*3:今度見に行こう・・・

*4:業務アプリを作る必要が無くなる、という意であると思われる