トップ 最新 追記

Masa's blog

検索キーワード:

2009年06月03日 request_module[net-pf-10]: waitpid(3788,...) failed, errno 1 [長年日記]

_ request_module[net-pf-10]: waitpid(3788,...) failed, errno 1

2, 3日前からlib100の/val/log/syslogに

request_module[net-pf-10]: waitpid(3788,...) failed, errno 1

のメッセージが連続して記録されている。なんやらIPV6関係のモジュールをロードしようとして失敗しているようなのだが、そもそもIPV6での接続などしていないので何故このようなメッセージが出始めたのかは不明。

とりあえず、

$ egrep -i ipv6 /usr/src/linux/.config
# CONFIG_IPV6 is not set

の設定にして(IPV6を外して)カーネルを再構築中。

_ firefox-3.0.10 version up

.mozconfig

. $topsrcdir/browser/config/mozconfig
ac_add_options --disable-debug
ac_add_options --disable-dbus
ac_add_options --disable-jemalloc
ac_add_options --enable-optimize
ac_add_options --enable-default-toolkit=cairo-gtk2

build

nice make -f client.mk build
nice make package

2009年06月04日 request_module[net-pf-10]: waitpid(3788,...) failed, errno 1 (その2) [長年日記]

_ request_module[net-pf-10]: waitpid(3788,...) failed, errno 1 (その2)

カーネル再構築でもメッセージは消えなかった。その後 /etc/modprobe.conf に

install ipv6 /sbin/modprobe -n -i ipv6

を記述する方法も試したが効果無し。

_ sendmailに関係する?

その後、/var/log/messagesと/var/log/syslogを同時にtail -fで表示させて観察していると、どうやら外部からメールが到着してsendmailにキックがかかると、上記のエラーが発生しているらしいことを発見した。


2009年06月05日 Java儂(わし)的解釈によるメモ [長年日記]

_ Java儂(わし)的解釈によるメモ

COBOLERのおっさんによる、まったく身勝手な解釈によるJavaの小さな小さなサンプル集。とりあえずテキスト処理とネットワークプログラミングが出来ることを目標としてる。

hello.java

//
// Hello world
//
// compile : javac -encoding utf-8 hello.java
// run     : java -cp . hello
//
public class hello {
	public static void main(String[] args) {
		System.out.println("Hello java world.");
	}
}

クラスの中で定義されているメソッドは、通常そのクラスがnew(生成)されて初めて実体となり、呼び出す事ができるのだが、メッソドであるmain()は自分が属するhelloクラスが誰からもnew(生成)されていないにもかかわらず、呼び出す事ができている。

それは static という宣言に関係している。

staticの無いメソッドや変数の宣言の場合、それらはnew(生成)されたオブジェクトの内部に初めて実体として出現する。それに対して static で宣言されたメソッドや変数はクラスの定義そのものに実体を宿す。

よって、誰からもnew(生成)されなくても、既に存在しているので呼び出す事が可能となっている。

hello.java - 実行結果

Hello java world.

var.java - 変数

//
// 「変数」テスト
//
// compile : javac -encoding utf-8 var.java
// run     : java -cp . var
//
public class var {
	public static void main(String[] args) {
//
// 変数宣言
//
		byte  	wk_byte;
		short 	wk_short;
		int 	wk_int;
		long 	wk_long;
		float 	wk_float;
		double 	wk_double;
		char 	wk_char; // 内部表現はUnicodeとなる
		char 	wk_nchar; // 内部表現はUnicodeとなる
		boolean wk_boolean;
		String	wk_String; // 内部表現はUnicodeとなる
//
// 変数へ代入
//
		wk_byte = 10;
		wk_short = 10;
		wk_int = 10;
		wk_long = 10;
		wk_float = 10.1F;
		wk_double = 10.1;
		wk_char = 'A';
		wk_nchar = 'あ';
		wk_boolean = true;
		wk_String = "abcdefg";
//
// 変数を参照
//
		System.out.println("wk_byte=" + wk_byte);
		System.out.println("wk_short=" + wk_short);
		System.out.println("wk_int=" + wk_int);
		System.out.println("wk_long=" + wk_long);
		System.out.println("wk_float=" + wk_float);
		System.out.println("wk_double=" + wk_double);
		System.out.println("wk_char=" + wk_char);
		System.out.println("wk_nchar=" + wk_nchar);
		System.out.println("wk_boolean=" + wk_boolean);
		System.out.println("wk_String=" + wk_String);
	}
}

byte から booleanはjavaの言語仕様としてサポートされる基本型。charはUNICODEでデータを保持するので、従来言っていた「半角文字」「全角文字」(この表現自体どうかと思うが、他にうまく言えないので...)の区別無く「一文字」を格納できる。

最後に出てきた Stringは「型」ではなく「クラス」。C言語が文字列を、「言語仕様で直接サポートするchar型」の配列として扱っていたのと似ている。

var.java - 実行結果

wk_byte=10
wk_short=10
wk_int=10
wk_long=10
wk_float=10.1
wk_double=10.1
wk_char=A
wk_nchar=あ
wk_boolean=true
wk_String=abcdefg

var_array.java - 配列

//
// 「配列」テスト
//
// compile : javac -encoding utf-8 var_array.java
// run     : java -cp . var_array
//
public class var_array {
	public static void main(String[] args) {
//
// 配列の初期化
//
		int[]	wk_int1 = new int[10];
		int[]	wk_int2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
//
// 配列への代入
//
		wk_int1[0] = 0;
		wk_int1[9] = 9;
//
// 配列の参照
//
		System.out.println("wk_int1.length=" + wk_int1.length);
		System.out.println("wk_int1[0]=" + wk_int1[0]);
		System.out.println("wk_int1[5]=" + wk_int1[5]);
		System.out.println("wk_int1[9]=" + wk_int1[9]);
		System.out.println("wk_int2.length=" + wk_int2.length);
		System.out.println("wk_int2[0]=" + wk_int2[0]);
		System.out.println("wk_int2[5]=" + wk_int2[5]);
		System.out.println("wk_int2[9]=" + wk_int2[9]);
	}
}

var_array.java - 実行結果

wk_int1.length=10
wk_int1[0]=0
wk_int1[5]=0
wk_int1[9]=9
wk_int2.length=10
wk_int2[0]=0
wk_int2[5]=5
wk_int2[9]=9

var_hash.java - ハッシュ

//
// 「ハッシュ」テスト
//
// compile : javac -encoding utf-8 var_hash.java
// run     : java -cp . var_hash
//
import java.util.*;

public class var_hash {
	public static void main(String[] args) {
//
// ハッシュ作成
//
		HashMap<String, String> map = new HashMap<String, String>();
//
// ハッシュに格納
//
		map.put("apple", "red");
		map.put("melon", "green");
		map.put("lemon", "yellow");
//
// ハッシュを参照
//
		System.out.println("melon = " + map.get("melon"));
		System.out.println("apple = " + map.get("apple"));
		System.out.println("lemon = " + map.get("lemon"));
//
// キーの数だけ繰り返す
//
		Iterator ite = map.keySet().iterator();
		while (ite.hasNext()){
			Object s = ite.next();
			System.out.println(s.toString() + " = " + map.get(s.toString()) + " by keySet");
		}
//
// キー順ハッシュ作成
//
		TreeMap<String, String> tmap = new TreeMap<String, String>(map);
//
// キーの数だけ繰り返す
//
		for (String s : tmap.keySet()){
			System.out.println(s + " = " + tmap.get(s) + " by TreeMap+keySet");
		}
//
// キー指定で削除
//
		map.remove("apple");

		for (String s : map.keySet()){
			System.out.println(s + " = " + map.get(s) + " by apple removed");
		}
	}
}

var_hash.java - 実行結果

melon = green
apple = red
lemon = yellow
melon = green by keySet
apple = red by keySet
lemon = yellow by keySet
apple = red by TreeMap+keySet
lemon = yellow by TreeMap+keySet
melon = green by TreeMap+keySet
melon = green by apple removed
lemon = yellow by apple removed

var_linkedlist.java - リンクリスト

//
// 「LinkedList」テスト
//
// compile : javac -encoding utf-8 var_linkedlist.java
// run     : java -cp . var_linkedlist
//
import java.util.*;

public class var_linkedlist {
	public static void main(String[] args) {
//
// リストの初期化
//
		LinkedList<String>	ll = new LinkedList<String>();
//
// リストへの代入
//
		ll.add("文字列1");
		ll.add("文字列2");
		ll.add("文字列3");
		ll.add("文字列4");
		ll.add("文字列5");
//
// 要素数取得
//
		System.out.println("size = " + ll.size());
//
// 直接参照
//
		System.out.println("ll.get(2) = " + ll.get(2));
//
// 直接置換
//
		ll.set(2, "置換された文字列3");
//
// リストの参照
//
		Iterator ite = ll.iterator();
		while (ite.hasNext()){
			System.out.println(ite.next());
		}
//
// リストからの削除
//
		ll.remove();	// 先頭の削除
		ll.remove(2);	// 2番目(0オリジンで)の削除
//
// リストの参照
//
		ite = ll.iterator();
		while (ite.hasNext()){
			System.out.println(ite.next());
		}
	}
}

実行結果

size = 5
ll.get(2) = 文字列3
文字列1
文字列2
置換された文字列3
文字列4
文字列5
文字列2
置換された文字列3
文字列5

var_henkan.java - 型変換

//
// 「型変換」テスト
//
// compile : javac -encoding utf-8 var_henkan.java
// run     : java -cp . var_henkan
//
public class var_henkan {
	public static void main(String[] args) {
		int	wk_int;
		long	wk_long;
		Integer	wk_Integer;
		Long	wk_Long;
//
// 文字列 -> 数値
//
		wk_int = Integer.valueOf("256");
		wk_long = Long.valueOf("256");
		System.out.println("wk_int + wk_long = " + (wk_int + wk_long) + " by valueOf");
//
// 文字列 -> 数値オブジェクト
//
		wk_Integer = Integer.parseInt("256");
		wk_Long = Long.parseLong("256");
		System.out.println("wk_Integer + wk_Long = " + (wk_Integer + wk_Long) + " by parse{Int|Long}");
//
// 数値 -> 文字列
//
		String str_int = Integer.toString(256);
		String str_long = Long.toString(256);
		System.out.println("str_int + str_long = " + (str_int + str_long) + " by toString");
	}
}

Float, Doubleに関しても同じような感じでいける ;)

var_henkan.java - 実行結果

wk_int + wk_long = 512 by valueOf
wk_Integer + wk_Long = 512 by parse{Int|Long}
str_int + str_long = 256256 by toString

string_hikisu.java - 引数

//
// 「引数」テスト
//
// compile : javac -encoding utf-8 string_hikisu.java
// run     : java -cp . string_hikisu
//
public class string_hikisu {
	public static void main(String[] args) {
//
// 引数の個数
//
		System.out.println("args.length=" + args.length);
//
// 引数の参照
//
		for (int i = 0; i < args.length; i++){
			System.out.println("args[" + i + "]=" + args[i]);
		}
	}
}

string_hikisu.java - 実行結果

$ java string_hikisu aaa bbb
args.length=2
args[0]=aaa
args[1]=bbb

string_indexOf.java - 文字列位置

//
// 「indexOf」テスト
//
// compile : javac -encoding utf-8 string_indexOf.java
// run     : java -cp . string_indexOf
//
public class string_indexOf {
	public static void main(String[] args) {
//
// 文字列の位置
//
		String str = "123456789";
		System.out.println("position 567 in " + str + " is " + str.indexOf("567"));
	}
}

string_indexOf.java - 実行結果

position 567 in 123456789 is 4

string_length.java - 文字列長

//
// 「length」テスト
//
// compile : javac -encoding utf-8 string_length.java
// run     : java -cp . string_length
//
public class string_length {
	public static void main(String[] args) {
//
// 文字列長
//
		String str = "123456789";
		System.out.println("length of " + str + " is " + str.length());
//
// 日本語を含む場合の文字列長
//
		str = "漢字はどうなる?";
		System.out.println("length of " + str + " is " + str.length());
	}
}

string_length.java - 実行結果

length of 123456789 is 9
length of 漢字はどうなる? is 8

string_mojihenkan.java - 文字コード変換

//
// 「文字コード変換」テスト
//
// compile : javac -encoding utf-8 string_mojihenkan.java
// run     : java -cp . string_mojihenkan
//
import java.io.*;

public class string_mojihenkan {
	public static void main(String[] args) {
		String str = "javaのStringはunicodeで表現される\n";

		try {
//
// 文字コードをUNICODE(java内部表現)から変換
//
//			byte[] bt = str.getBytes("JIS");
//			byte[] bt = str.getBytes("SHIFT_JIS");
//			byte[] bt = str.getBytes("UTF-8");
			byte[] bt = str.getBytes("EUC-JP");
			System.out.write(bt);
		} catch(UnsupportedEncodingException e) {
			System.out.println("encoding error happened : " + e);
		} catch(IOException e) {
			System.out.println("write error happened : " + e);
		}
	}
}

string_mojihenkan.java - 実行結果

javaのStringはunicodeで表現される

string_replaceAll.java - 正規表現による文字列置換

//
// 「replaceAll」テスト
//
// compile : javac -encoding utf-8 string_replaceAll.java
// run     : java -cp . string_replaceAll
//
public class string_replaceAll {
	public static void main(String[] args) {
//
// 正規表現で文字列置換
//
		String str_before = "ABCDEFGHIJKLMN";
		String str_after = str_before.replaceAll("B.*M", "B to M");
		System.out.println("str_before = " + str_before);
		System.out.println("str_after = " + str_after);
	}
}

string_replaceAll.java - 実行結果

str_before = ABCDEFGHIJKLMN
str_after = AB to MN

string_split.java - 文字列分割

//
// 「split」テスト
//
// compile : javac -encoding utf-8 string_split.java
// run     : java -cp . string_split
//
public class string_split {
	public static void main(String[] args) {
//
// 文字列分割
//
		String str = "apple,lemon,,orange,,,lemon";
		String[] strArry = str.split(",,*");
		for (int i = 0; i < strArry.length; i++){
			System.out.println("strArry[" + i + "] = " + strArry[i]);
		}

//
// 文字列分割(分割制限有り)
//
		str = "apple,lemon,orange,lemon";
		strArry = str.split(",", 3);
		for (int i = 0; i < strArry.length; i++){
			System.out.println("strArry[" + i + "] = " + strArry[i] + " by limited 3");
		}
	}
}

string_split.java - 実行結果

strArry[0] = apple
strArry[1] = lemon
strArry[2] = orange
strArry[3] = lemon
strArry[0] = apple by limited 3
strArry[1] = lemon by limited 3
strArry[2] = orange,lemon by limited 3

string_scanner.java - 文字列分割

//
// 「scanner」テスト
//
// compile : javac -encoding utf-8 string_scanner.java
// run     : java -cp . string_scanner
//
import java.util.*;

public class string_scanner {
        public static void main(String[] args) throws Exception {
//
//              Scanner s = new Scanner(System.in); // こんな感じに、引数にストリームも指定可能
//
                Scanner s = new Scanner("apple,lemon,,orange,,,lemon");
                s.useDelimiter(",,*");
                while (s.hasNext()) {
                        System.out.println(s.next());
                }
        }
}

string_scanner.java - 実行結果

apple
lemon
orange
lemon

string_substring.java - 文字列部分参照

//
// 「substring」テスト
//
// compile : javac -encoding utf-8 string_substring.java
// run     : java -cp . string_substring
//
public class string_substring {
	public static void main(String[] args) {
//
// 文字列部分参照(アルファベット)
//
		String str = "123456789";
		System.out.println("str = " + str);
		System.out.println("str.substring(3, 6) = " + str.substring(3, 6));
//
// 文字列部分参照(漢字)
//
		str = "あいうえおかきくけこ";
		System.out.println("str = " + str);
		System.out.println("str.substring(3, 6) = " + str.substring(3, 6));
//
// 文字列部分参照(アルファベット&漢字混在)
//
		str = "あAいBうCえDお";
		System.out.println("str = " + str);
		System.out.println("str.substring(3, 6) = " + str.substring(3, 6));
	}
}

string_substring.java - 実行結果

str = 123456789
str.substring(3, 6) = 456
str = あいうえおかきくけこ
str.substring(3, 6) = えおか
str = あAいBうCえDお
str.substring(3, 6) = BうC

if_test.java - 条件分岐

//
// 「if」テスト
//
// compile : javac -encoding utf-8 if_test.java
// run     : java -cp . if_test
//
import java.util.regex.*;

public class if_test {
	public static void main(String[] args) {
		int i = 10;
//
// 数値比較
//
		if (i > 0){
			System.out.println(i + " is plus");
		}else if (i == 0){
			System.out.println(i + " is zero");
		}else{
			System.out.println(i + " is minus");
		}
//
// 文字列比較
//
		String s = "ABCDE";

		if (s.compareTo("BCDEF") > 0){
			System.out.println(s + " > BCDEF");
		}else if (s.compareTo("BCDEF") == 0){
			System.out.println(s + " = BCDEF");
		}else{
			System.out.println(s + " < BCDEF");
		}
//
// 文字列比較(その他)
//
//		if (s.equals("BCDEF")){
//			等しい時の処理
//		}else{
//			等しくない時の処理
//		}
//

//
// 正規表現比較
//
		Pattern pattern = Pattern.compile("^A.*E$");
		Matcher matcher = pattern.matcher(s);

//
// 		if (matcher.find()){ // 部分比較
//
		if (matcher.matches()){ // 全領域比較
			System.out.println(s + " matches to /^A.*E$/");
		}else{
			System.out.println(s + " not matches to /^A.*E$/");
		}
//
//		if (s.matches("^A.*E$)){
//			実は、Stringクラスにも matchesメソッはありました...
//		}
//

	}
}

if_test.java - 実行結果

10 is plus
ABCDE < BCDEF
ABCDE matches to /^A.*E$/

switch_test.java - 条件多分岐

//
// 「switch」テスト
//
// compile : javac -encoding utf-8 switch_test.java
// run     : java -cp . switch_test
//
import java.util.regex.*;

public class switch_test {
	public static void main(String[] args) {
		int i = 10;

		switch (i){
		case 1:
			System.out.println(i + " is 1");
			break;
		case 10:
			System.out.println(i + " is 10");
			break;
		default:
			System.out.println(i + " is not 1 and 10");
			break;
		}
	}
}

switch_test.java - 実行結果

10 is 10

while_test.java - 繰り返し

//
// 「while」テスト
//
// compile : javac -encoding utf-8 while_test.java
// run     : java -cp . while_test
//
public class while_test {
	public static void main(String[] args) {
//
// while(条件有り)
//
		int i = 0;
		while (i < 10){
			System.out.println("i = " + i);
			i++;
		}
//
// while(永久ループ & breakによる中断)
//
		i = 0;
		while (true){
			System.out.println("i = " + i + " terminated by break");
			if (i > 10){
				break;
			}
			i++;
		}
	}
}

while_test.java - 実行結果

i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
i = 0 terminated by break
i = 1 terminated by break
i = 2 terminated by break
i = 3 terminated by break
i = 4 terminated by break
i = 5 terminated by break
i = 6 terminated by break
i = 7 terminated by break
i = 8 terminated by break
i = 9 terminated by break
i = 10 terminated by break
i = 11 terminated by break

for_test.java - 繰り返し(2)

//
// 「for」テスト
//
// compile : javac -encoding utf-8 for_test.java
// run     : java -cp . for_test
//
import java.util.*;

public class for_test {
	public static void main(String[] args) {
//
// for文
//
		for (int i = 0; i < 10; i++){
			System.out.println("i =" + i);
		}
//
// for文(配列分だけ繰り返す)
//
               String[] arry = {"apple", "melon", "lemon"};
               for (String thing: arry){
                       System.out.println("thing =" + thing);
               }

//
// for文(ハッシュのキー分だけ繰り返す)
//
		HashMap<String, String> map = new HashMap<String, String>();

		map.put("apple", "red");
		map.put("melon", "green");
		map.put("lemon", "yellow");

		for (String s : map.keySet()){
			System.out.println(s + " = " + map.get(s));
		}

	}
}

for_test.java - 実行結果

i =0
i =1
i =2
i =3
i =4
i =5
i =6
i =7
i =8
i =9
thing =apple
thing =melon
thing =lemon
melon = green
apple = red
lemon = yellow

function_test.java - 関数

//
// 「function」テスト
//
// compile : javac -encoding utf-8 function_test.java
// run     : java -cp . function_test
//
public class function_test {
	public static void main(String[] args) {
		function_test main = new function_test();
		String str = main.my_func("arg1", "arg2");
		System.out.println(str);

		function_test_my_class mc = new function_test_my_class();
		str = mc.my_func2("ARG1", "ARG2");
		System.out.println(str);
	}
//
// 同一クラス内のファンクション
//
	String my_func(String arg1, String arg2){
		return arg1 + " and " + arg2;
	}
}

class function_test_my_class {
//
// 同一クラス外のファンクション
//
	String my_func2(String arg1, String arg2){
		return arg1 + " and " + arg2;
	}
}

ちよっと奇妙に思うかもしれないが、mainメソッドの中で自分の属するクラス(function_test)をnew(生成)している。一見無限ループを起こすかのように思うかもしれないが問題ない。

staticなメソッド、変数を含むクラスをnew(生成)した場合は、staticなもの以外が動的に生成されるだけなので、mainメソッドがいくつも出来てループ状態になる...という事は無い。

上記の場合、newすることで生成された main オブジェクトを介して mainメソッドは自分の属するクラスの(staticでない)メソッドや変数にアクセスできるようになる。

また、mainメソッドを含むクラスをnew(生成)しなかった場合はどうかというと、mainメソッドは自分の属するクラスのメソッドや変数であっても、static宣言されたものしかアクセスできない。なぜならnew(生成)されない限りそれらは存在しないから。

function_test.java - 実行結果

arg1 and arg2
ARG1 and ARG2

getenv_test.java - 環境変数取得

//
// 「getenv」テスト
//
// compile : javac -encoding utf-8 getenv_test.java
// run     : java -cp . getenv_test
//
public class getenv_test {
	public static void main(String[] args) {
//
// 環境変数 PATH 取得
//
		System.out.println(System.getenv("LC_ALL"));
	}
}

getenv_test.java - 実行結果

ja_JP.eucJP

get_datetime.java - 日付、時刻の取得

//
// 「日時取得」テスト
//
// compile : javac -encoding utf-8 get_datetime.java
// run     : java -cp . get_datetime
//
import java.util.Calendar;

public class get_datetime {
	public static void main(String[] args) {
		Calendar cal = Calendar.getInstance();

		int year = cal.get(cal.YEAR);
		int month = cal.get(cal.MONTH) + 1;
		int day = cal.get(cal.DATE);

		int hour = cal.get(cal.HOUR_OF_DAY);
		int minute = cal.get(cal.MINUTE);
		int second = cal.get(cal.SECOND);
		int millisecond = cal.get(cal.MILLISECOND);

		System.out.printf("%04d/%02d/%02d %02d:%02d:%02d.%03d\n", year, month, day, hour, minute, second, millisecond);
	}
}

get_datetime.java - 実行結果

2009/06/05 22:26:47.095

exec_program.java - OSコマンド実行(バックグラウンドで実行し、親子で通信あり)

//
// 「外部コマンド実行」テスト
//
// compile : javac -encoding utf-8 exec_program.java
// run     : java -cp . exec_program
//
import java.io.*;

public class exec_program {
	public static void main(String[] args) {
		try {
//
// 実行
//
			Process process = Runtime.getRuntime().exec("ls -al *.java");
//
// 起動プロセスのstdout
//
			InputStream isout = process.getInputStream();
			InputStreamReader isoutr = new InputStreamReader(isout, "EUC-JP");
			BufferedReader brout = new BufferedReader(isoutr);
//
// 起動プロセスのstderr(使わないけど)
//
			InputStream iserr = process.getErrorStream();
			InputStreamReader iserrr = new InputStreamReader(iserr, "EUC-JP");
			BufferedReader brerr = new BufferedReader(iserrr);
//
// 起動プロセスのstdin(使わないけど)
//
			OutputStream osin = process.getOutputStream();
			OutputStreamWriter osinr = new OutputStreamWriter(osin, "EUC-JP");
//
// 結果受取り
//
			String str;
			while ((str = brout.readLine()) != null) {
				System.out.println(str);
			}
//
// クローズ
//
			brout.close();
			isoutr.close();
			isout.close();

			brerr.close();
			iserrr.close();
			iserr.close();

			osinr.close();
			osin.close();
		} catch (Exception e) {
			System.out.println(e);
		}
	}
}

exec_program.java - 実行結果

-rw-r--r--    1 m-ito    users        3184  5月 31 00:51 class_test.java
-rw-r--r--    1 m-ito    users        1206  6月  4 14:26 exec_program.java
-rw-r--r--    1 m-ito    users        1317  6月  2 23:06 file_buffered_read.java
-rw-r--r--    1 m-ito    users         687  6月  2 23:08 file_delete.java
-rw-r--r--    1 m-ito    users         452  6月  4 12:45 file_mkdir.java
-rw-r--r--    1 m-ito    users        1433  6月  4 14:22 file_printf.java
-rw-r--r--    1 m-ito    users         769  6月  4 14:23 file_rename.java
-rw-r--r--    1 m-ito    users        1094  6月  2 23:09 file_stream_read.java
-rw-r--r--    1 m-ito    users        1579  6月  2 23:18 file_stream_write.java
-rw-r--r--    1 m-ito    users         551  6月  2 23:20 for_test.java
-rw-r--r--    1 m-ito    users         649  6月  2 23:24 function_test.java
-rw-r--r--    1 m-ito    users         624  6月  4 14:25 get_datetime.java
-rw-r--r--    1 m-ito    users         248  6月  2 23:24 getenv_test.java
-rw-r--r--    1 m-ito    users         195  6月  4 12:43 hello.java
-rw-r--r--    1 m-ito    users         886  6月  2 23:44 if_test.java
-rw-r--r--    1 m-ito    users         369  6月  4 16:00 string_hikisu.java
-rw-r--r--    1 m-ito    users         313  6月  4 15:53 string_indexOf.java
-rw-r--r--    1 m-ito    users         423  6月  4 15:54 string_length.java
-rw-r--r--    1 m-ito    users         706  6月  4 15:55 string_mojihenkan.java
-rw-r--r--    1 m-ito    users         431  6月  4 15:56 string_replaceAll.java
-rw-r--r--    1 m-ito    users         620  6月  4 15:56 string_split.java
-rw-r--r--    1 m-ito    users         722  6月  4 15:59 string_substring.java
-rw-r--r--    1 m-ito    users         417  5月 29 13:56 switch_test.java
-rw-r--r--    1 m-ito    users        1229  6月  4 12:21 tcpip_client.java
-rw-r--r--    1 m-ito    users        1698  6月  4 12:30 tcpip_multi_server.java
-rw-r--r--    1 m-ito    users        1227  6月  4 12:38 tcpip_server.java
-rw-r--r--    1 m-ito    users        1155  6月  2 13:28 thread_test.java
-rw-r--r--    1 m-ito    users         991  6月  4 15:52 var.java
-rw-r--r--    1 m-ito    users         764  6月  4 16:01 var_array.java
-rw-r--r--    1 m-ito    users        1088  6月  4 15:58 var_hash.java
-rw-r--r--    1 m-ito    users         871  6月  4 15:51 var_henkan.java
-rw-r--r--    1 m-ito    users         448  6月  4 12:39 while_test.java

exec_program.java - OSコマンド実行(単純起動)

//
// 「外部コマンド実行」テスト
//
// compile : javac -encoding utf-8 exec_program.java
// run     : java -cp . exec_program
//
import java.io.*;

public class exec_program {
	public static void main(String[] args) {
		try {
//
// 実行
//
			Process process = Runtime.getRuntime().exec("ls -al *.java");
//
// 終了を待ち合わせる
//
			int ret = process.waitFor();
		} catch (Exception e) {
			System.out.println(e);
		}
	}
}

file_stream_write.java - ファイル出力

//
// 「ファイル出力(ストリーム)」テスト
//
// compile : javac -encoding utf-8 file_stream_write.java
// run     : java -cp . file_stream_write
//
import java.io.*;

public class file_stream_write {
	public static void main(String[] args) {
//
// ファイルへの出力
//
		try {
			FileOutputStream fos = new FileOutputStream("file_stream_write.txt");
			OutputStreamWriter osw = new OutputStreamWriter(fos, "EUC-JP");

			osw.write("これは line1\n");
			osw.write("これは line2\n");
			osw.write("これは line3\n");
			osw.write("これは line4\n");
			osw.write("これは line5\n");

			osw.close();
			fos.close();
		} catch(IOException e) {
			System.out.println("write error happened : " + e);
		} finally {
		}
//
// 標準出力への出力
//
		try {
			OutputStreamWriter osw = new OutputStreamWriter(System.out, "EUC-JP");

			osw.write("this is line1 to stdout\n");
			osw.write("this is line2 to stdout\n");
			osw.write("this is line3 to stdout\n");
			osw.write("this is line4 to stdout\n");
			osw.write("this is line5 to stdout\n");

			osw.close();
		} catch(IOException e) {
			System.out.println("write error happened : " + e);
		} finally {
		}
//
// エラー出力への出力
//
		try {
			OutputStreamWriter osw = new OutputStreamWriter(System.err, "EUC-JP");

			osw.write("this is line1 to stderr\n");
			osw.write("this is line2 to stderr\n");
			osw.write("this is line3 to stderr\n");
			osw.write("this is line4 to stderr\n");
			osw.write("this is line5 to stderr\n");

			osw.close();
		} catch(IOException e) {
			System.out.println("write error happened : " + e);
		} finally {
		}
	}
}

file_stream_write.java - 実行結果

$ java file_stream_write
this is line1 to stdout
this is line2 to stdout
this is line3 to stdout
this is line4 to stdout
this is line5 to stdout
this is line1 to stderr
this is line2 to stderr
this is line3 to stderr
this is line4 to stderr
this is line5 to stderr
$ cat file_stream_write.txt
これは line1
これは line2
これは line3
これは line4
これは line5

【追記】追加書き込み

中核部分だけ

FileOutputStream fos = new FileOutputStream("file_stream_write.txt", true);
OutputStreamWriter osw = new OutputStreamWriter(fos, "EUC-JP");

osw.write("この行は最後に追加されます。\n");

osw.close();
fos.close();

file_printf.java - 書式付きファイル出力

//
// 「printf」テスト
//
// compile : javac -encoding utf-8 file_printf.java
// run     : java -cp . file_printf
//
import java.io.*;

public class file_printf {
	public static void main(String[] args) {
//
// ファイルへの出力
//
		try {
			FileOutputStream fos = new FileOutputStream("file_printf.txt");
//
// "true" in second argument means "auto flush"
//
			PrintStream ps = new PrintStream(fos, true, "EUC-JP");

			for (int i = 0; i < 3; i++){
				ps.printf("i = %d, i*i = %d, 3.14*i*i = %f\n", i, i*i , 3.14*i*i);
			}

			ps.close();
			fos.close();
		} catch(IOException e) {
			System.out.println("write error happened : " + e);
		} finally {
		}
//
// 標準出力への出力
//
		try {
			PrintStream ps = new PrintStream(System.out, true, "EUC-JP");

			for (int i = 0; i < 3; i++){
				ps.printf("i = %d, i*i = %d, 3.14*i*i = %f to stdout\n", i, i*i , 3.14*i*i);
			}

			ps.close();
		} catch(IOException e) {
			System.out.println("write error happened : " + e);
		} finally {
		}
//
// エラー出力への出力
//
		try {
			PrintStream ps = new PrintStream(System.err, true, "EUC-JP");

			for (int i = 0; i < 3; i++){
				ps.printf("i = %d, i*i = %d, 3.14*i*i = %f to stderr\n", i, i*i , 3.14*i*i);
			}

			ps.close();
		} catch(IOException e) {
			System.out.println("write error happened : " + e);
		} finally {
		}
//
// 標準出力、エラー出力への出力の別解
//
//		System.out.printf("This printf is right too! to stdout\n");
//		System.err.printf("This printf is right too! to stderr\n");
	}
}

file_printf.java - 実行結果

$ java file_printf
i = 0, i*i = 0, 3.14*i*i = 0.000000 to stdout
i = 1, i*i = 1, 3.14*i*i = 3.140000 to stdout
i = 2, i*i = 4, 3.14*i*i = 12.560000 to stdout
i = 0, i*i = 0, 3.14*i*i = 0.000000 to stderr
i = 1, i*i = 1, 3.14*i*i = 3.140000 to stderr
i = 2, i*i = 4, 3.14*i*i = 12.560000 to stderr
$ cat file_printf.txt
i = 0, i*i = 0, 3.14*i*i = 0.000000
i = 1, i*i = 1, 3.14*i*i = 3.140000
i = 2, i*i = 4, 3.14*i*i = 12.560000

【追記】書式付き文字列変換

中核部分だけ抜粋

FileOutputStream fos = new FileOutputStream("file_stream_write.txt");
// OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
// OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-16");
// OutputStreamWriter osw = new OutputStreamWriter(fos, "Shift_JIS");
OutputStreamWriter osw = new OutputStreamWriter(fos, "EUC-JP");

osw.write(String.format("%s\n", "これは line1"));

osw.close();
fos.close();

file_stream_read.java - ファイル入力(ストリーム)

//
// 「ファイル入力(ストリーム)」テスト
//
// compile : javac -encoding utf-8 file_stream_read.java
// run     : java -cp . file_stream_read
//
import java.io.*;

public class file_stream_read {
	public static void main(String[] args) {
//
// ファイルからの入力
//
		try {
			FileInputStream fis = new FileInputStream("file_stream_write.txt");
			InputStreamReader isr = new InputStreamReader(fis, "EUC_JP");

			int ch;
//
// fis.read() を使うと変換せずに(バイナリファイルとして)読み込んで来る。
// isr.read() はunicodeに変換しながら読み込んで来る。
//
			while ((ch = isr.read()) != -1){
				System.out.print((char)ch);
			}

			isr.close();
			fis.close();
		} catch(IOException e) {
			System.out.println("read error happened : " + e);
		} finally {
		}
//
// 標準入力からの入力
//
		System.out.println("Please input something : ");
		try {
			InputStreamReader isr = new InputStreamReader(System.in, "EUC-JP");

			int ch;
			while ((ch = isr.read()) != -1){
				System.out.print((char)ch);
			}

			isr.close();
		} catch(IOException e) {
			System.out.println("read error happened : " + e);
		} finally {
		}
	}
}

file_stream_read.java - 実行結果

これは line1
これは line2
これは line3
これは line4
これは line5
Please input something :
This is java.
This is java.
^D

file_buffered_read.java - ファイル入力(行単位)

//
// 「ファイル入力(バッファード)」テスト
//
// compile : javac -encoding utf-8 file_buffered_read.java
// run     : java -cp . file_buffered_read
//
import java.io.*;

public class file_buffered_read {
	public static void main(String[] args) {
//
// ファイルからの入力
//
		try {
// ファイル開く(文字コード変換無し)
			FileInputStream fis = new FileInputStream("file_stream_write.txt");
// 入力ストリーム(文字コード変換あり EUC-JP -> UNICODE)
			InputStreamReader isr = new InputStreamReader(fis, "EUC-JP");
// 行入力ストリーム
			BufferedReader br = new BufferedReader(isr);

			String line;
			while ((line = br.readLine()) != null) {
				System.out.println(line);
			}

			br.close();
			isr.close();
			fis.close();
		} catch(IOException e) {
			System.out.println("read error happened : " + e);
		} finally {
		}
//
// 標準入力からの入力
//
		System.out.println("Please input something : ");
		try {
// 入力ストリーム(文字コード変換あり EUC-JP -> UNICODE)
			InputStreamReader isr = new InputStreamReader(System.in, "EUC-JP");
// 行入力ストリーム
			BufferedReader br = new BufferedReader(isr);

			String line;
			while ((line = br.readLine()) != null) {
				System.out.println(line);
			}

			br.close();
			isr.close();
		} catch(IOException e) {
			System.out.println("read error happened : " + e);
		} finally {
		}
	}
}

file_buffered_read.java - 実行結果

これは line1
これは line2
これは line3
これは line4
これは line5
Please input something :
This is java.
This is java.
^D

file_delete.java - ファイル削除

//
// 「delete」テスト
//
// compile : javac -encoding utf-8 file_delete.java
// run     : java -cp . file_delete
//
import java.io.*;

public class file_delete {
	public static void main(String[] args) {
//
// 準備
//
		try {
			FileOutputStream fos = new FileOutputStream("file_delete.txt");
			PrintStream ps = new PrintStream(fos, true, "EUC-JP");

			ps.printf("dummy data\n");

			ps.close();
			fos.close();
		} catch(IOException e) {
			System.out.println("write error happened : " + e);
		} finally {
		}
//
// 削除
//
		java.io.File f = new java.io.File("file_delete.txt");
		if (f.delete()){
			System.out.println("delete success");
		}else{
			System.out.println("delete failure");
		}
	}
}

file_delete.java - 実行結果

delete success

file_rename.java - ファイル名変更

//
// 「rename」テスト
//
// compile : javac -encoding utf-8 file_rename.java
// run     : java -cp . file_rename
//
import java.io.*;

public class file_rename {
	public static void main(String[] args) {
//
// 準備
//
		try {
			FileOutputStream fos = new FileOutputStream("file_rename.txt");
			PrintStream ps = new PrintStream(fos, true, "EUC-JP");

			ps.printf("dummy data\n");

			ps.close();
			fos.close();
		} catch(IOException e) {
			System.out.println("write error happened : " + e);
		} finally {
		}

//
// リネーム
//
		java.io.File before = new java.io.File("file_rename.txt");
		java.io.File after = new java.io.File("FILE_RENAME.TXT");
		if (before.renameTo(after)){
			System.out.println("rename success");
		}else{
			System.out.println("rename failure");
		}
	}
}

file_rename.java - 実行結果

rename success
$ ls | egrep -i file_rename.txt
FILE_RENAME.TXT

file_mkdir.java - ディレクトリ作成

//
// 「mkdir」テスト
//
// compile : javac -encoding utf-8 file_mkdir.java
// run     : java -cp . file_mkdir
//
import java.io.*;

public class file_mkdir {
	public static void main(String[] args) {
//
// 準備
//
		java.io.File d = new java.io.File("file_mkdir.dir");
		d.delete();
//
// ディレクトリ作成
//
		d = new java.io.File("file_mkdir.dir");
		if (d.mkdir()){
			System.out.println("mkdir success");
		}else{
			System.out.println("mkdir failure");
		}
	}
}

file_mkdir.java - 実行結果

mkdir success
$ ls -ald file_mkdir.dir
drwxr-xr-x    2 m-ito    users        4096  6月  5 22:51 file_mkdir.dir/

class_test.java - クラス

//
// 「class」テスト
//
// compile : javac -encoding utf-8 class_test.java
// run     : java -cp . class_test
//
// 一つのjavaソース内で、publicで宣言できるclassは一つだけ。
// なので、外部から参照されるクラス定義は独立したファイルで
// 作成する必要がある。
//
public class class_test {
	public static void main(String[] args) {
		class_test_my_class mc1 = new class_test_my_class();
		System.out.println("mc1 wk_class = " + mc1.get_wk_class());
		System.out.println("mc1 wk_instance = " + mc1.get_wk_instance());

		class_test_my_class mc2 = new class_test_my_class("WK_CLASS2", "WK_INSTANCE2");
		System.out.println("mc2 wk_class = " + mc2.get_wk_class());
		System.out.println("mc2 wk_instance = " + mc2.get_wk_instance());

		mc1.set_wk_class("WK_CLASS1");
		mc1.set_wk_instance("WK_INSTANCE1");
		System.out.println("mc1 wk_class = " + mc1.get_wk_class());
		System.out.println("mc1 wk_instance = " + mc1.get_wk_instance());
		System.out.println("mc2 wk_class = " + mc2.get_wk_class());
		System.out.println("mc2 wk_instance = " + mc2.get_wk_instance());

		class_test_my_class2 mc3 = new class_test_my_class2();
		System.out.println("mc3 wk_class = " + mc3.get_wk_class());
		System.out.println("mc3 wk_instance = " + mc3.get_wk_instance());
		System.out.println("mc3 wk_class2 = " + mc3.get_wk_class2());
		System.out.println("mc3 wk_instance2 = " + mc3.get_wk_instance2());

		mc3.set_wk_class("WK_CLASS3");
		mc3.set_wk_instance("WK_INSTANCE3");
		System.out.println("mc3 wk_class = " + mc3.get_wk_class());
		System.out.println("mc3 wk_instance = " + mc3.get_wk_instance());

               class_test_my_class2 mc4 = new class_test_my_class2("AAAAA", "BBBBB", "CCCCC", "DDDDD");
               System.out.println("mc4 wk_class = " + mc4.get_wk_class());
               System.out.println("mc4 wk_instance = " + mc4.get_wk_instance());
               System.out.println("mc4 wk_class2 = " + mc4.get_wk_class2());
               System.out.println("mc4 wk_instance2 = " + mc4.get_wk_instance2());
	}
}
//
// クラス(継承無し)
//
class class_test_my_class {
//
// クラス変数(このクラスから生成されたオブジェクト間で共通の領域)
//
	static String wk_class;
//
// インスタンス変数(オブジェクトごとに独立したな領域)
//
	String wk_instance;   // 指定無し 自ソースファイルのみからアクセスできる。
                              // public どこからも全く自由にアクセスできる。
                              // protected 自ソースファイルと、サブクラスのみからアクセスできる。
                              // private   自分自身のクラスのみからアクセスできる。
//
// コンストラクタ1(初期化メソッド)
//
	class_test_my_class(){
		wk_class = "initial wk_class";
		wk_instance = "initial wk_instance";
	}
//
// コンストラクタ2(初期化メソッド)
//
	class_test_my_class(String arg_class, String arg_instance){
		wk_class = arg_class;
		wk_instance = arg_instance;
	}
//
// メソッド
//
	String get_wk_class(){
		return wk_class;
	}

	String get_wk_instance(){
		return wk_instance;
	}

	void set_wk_class(String str){
		wk_class = str;
	}

	void set_wk_instance(String str){
		wk_instance = str;
	}

	void speak(){
		System.out.println("wk_class=" + wk_class);
		System.out.println("wk_instance=" + wk_instance);
	}
}

static で宣言された変数(およびメソッド)はクラス定義そのものの中に実体が有り、該当のクラスから生成されたオブジェクト間で共有される。

メソッドの名称がクラス名と同一のものはオブジェクトの初期化メソッド(コンストラクタと呼ぶ)となり、new(生成)の際に自動的に実行される。また、引数の違いにより複数の初期化メソッドを定義できる。

//
// クラス (class_test_my_classから継承)
//
class class_test_my_class2 extends class_test_my_class {
//
// クラス変数(このクラスから生成されたオブジェクト間で共通の領域)
//
	static String wk_class2;
//
// インスタンス変数(オブジェクトごとに独立したな領域)
//
	String wk_instance2;
//
// コンストラクタ(1)
//
	class_test_my_class2(){
		wk_class2 = "initial wk_class2";
		wk_instance2 = "initial wk_instance2";
	}
//
// コンストラクタ(2)
//
	class_test_my_class2(String arg_class, String arg_instance){
		wk_class2 = arg_class;
		wk_instance2 = arg_instance;
	}
//
// コンストラクタ(3)
//
	class_test_my_class2(String arg_class1, String arg_instance1, String arg_class2, String arg_instance2){
// 親クラスのコンストラクタの呼び出し
		super(arg_class1, arg_instance1);

		wk_class2 = arg_class2;
		wk_instance2 = arg_instance2;

// 意味は無いけど、親のメソッドを呼び出してみる
		super.speak();
	}
//
// メソッド
//
	String get_wk_class2(){
		return wk_class2;
	}

	String get_wk_instance2(){
		return wk_instance2;
	}

	void set_wk_class2(String str){
		wk_class2 = str;
	}

	void set_wk_instance2(String str){
		wk_instance2 = str;
	}
//
// 再定義(オーバーライド)
//
	void set_wk_class(String str){
		wk_class = str + " is setted in class_test_my_class2";
	}

	void set_wk_instance(String str){
		wk_instance = str + " is setted in class_test_my_class2";
	}
}

クラスの継承は extends にて指定する。

コンストラクタからは親のコンストラクタが引数無しで自動的に呼ばれる。明示的に呼び出す場合は super(引数,...) の形式で呼び出す。

親のメソッド、変数は super.メソッド(引数,...)、super.変数 の形式で呼び出す。

親で定義されたメソッドと同名のメソッドを定義する事で、親のメソッドを置き換える(再定義)することが出来る。

class_test.java - 実行結果

mc1 wk_class = initial wk_class
mc1 wk_instance = initial wk_instance
mc2 wk_class = WK_CLASS2
mc2 wk_instance = WK_INSTANCE2
mc1 wk_class = WK_CLASS1
mc1 wk_instance = WK_INSTANCE1
mc2 wk_class = WK_CLASS1
mc2 wk_instance = WK_INSTANCE2
mc3 wk_class = initial wk_class
mc3 wk_instance = initial wk_instance
mc3 wk_class2 = initial wk_class2
mc3 wk_instance2 = initial wk_instance2
mc3 wk_class = WK_CLASS3 is setted in class_test_my_class2
mc3 wk_instance = WK_INSTANCE3 is setted in class_test_my_class2
wk_class=AAAAA
wk_instance=BBBBB
mc4 wk_class = AAAAA
mc4 wk_instance = BBBBB
mc4 wk_class2 = CCCCC
mc4 wk_instance2 = DDDDD

class_test2.java - クラス(多態性)

//
// 「class(多態性)」テスト
//
// compile : javac -encoding utf-8 class_test2.java
// run     : java -cp . class_test2
//
class class_test2 {
	public static void main(String[] args){
		test1 t1 = new test1("test1");	// test1クラスにtest1オブジェクトを放り込む -> 当然
		test2 t2 = new test2("test21", "test22");	// test2クラスにtest2オブジェクトを放り込む -> 当然
		test1 t11 = new test2("test111", "test112");	// test1クラスにtest2オブジェクトを放り込む -> これが多態性!

		t1.show();	// test1オブジェクトのshow()を実行
		t2.show();	// test2オブジェクトのshow()を実行
		t11.show();	// test1オブジェクトからtest2のshow()を実行
	}
}
//
class test1 {
	String str1;
	test1(String s){
		str1 = s;
	}
	void show(){
		System.out.println(str1);
	}
}
//
class test2 extends test1 {
	String str2;
	test2(String s1, String s2){
		super(s1);
		str2 = s2;
	}
	void show(){
		System.out.println(str1 + "+" + str2);
	}
}

親クラスは子クラスを格納できる。これ多態性。

  • メモリ上に確保されたtest2クラスのオブジェクトの実体は以下を要素として持つ
    • String str1 <- test1で定義したもの
    • String str2 <- test2で定義したもの
    • void show() <- test2でオーバーライトしたもの
  • test1 t11は上記のオブジェクトをポイントする。
  • t11経由ではtest1の要素である以下のもののみアクセス(t11.ほげ)できる
    • String str1
    • void show()

ただし、メモリ上に確保されたtest2クラスのオブジェクトの実体内部では、当然全ての要素にアクセスできるので、test1のオブジェクトであるt11を経由して呼び出すshow()メソッドもString str2にアクセスすることが出来、正しく動作する。

class_test2.java - 実行結果

test1
test21+test22
test111+test112

class_test3.java - クラス(多態性2)

//
// 「class(多態性2)」テスト
//
// compile : javac -encoding utf-8 class_test3.java
// run     : java -cp . class_test3
//
class class_test3 {
	public static void main(String[] args){
		test2 t2 = new test1("test1");

		t2.show();
	}
}
//
class test1 {
	String str1;
	test1(String s){
		str1 = s;
	}
	void show(){
		System.out.println(str1);
	}
}
//
class test2 extends test1 {
	String str2;
	test2(String s1, String s2){
		super(s1);
		str2 = s2;
	}
	void show(){
		System.out.println(str1 + "+" + str2);
	}
}

子クラスは親クラスを格納できない。で、以下のようなコンパイルエラーが発生する。

class_test3.java - 実行結果

507 m-ito@lib190:~/src/java$ javac -encoding utf-8 !$
javac -encoding utf-8 class_test3.java
class_test3.java:3: 互換性のない型
検出値  : test1
期待値  : test2
                test2 t2 = new test1("test1");
                           ^
エラー 1 個
  • メモリ上に確保されたtest1クラスのオブジェクトの実体は以下を要素として持つ
    • String str1
    • void show()
  • test2 t2は上記のオブジェクトをポイントする。

この場合、t2.str2の実体がどこにも存在しないことになり不都合なので、javaコンパイラーはエラーを起こす(報告してくれる)。

implements_test.java - インターフェース

//
// 「implements」テスト
//
// compile : javac -encoding utf-8 implements_test.java
// run     : java -cp . implements_test
//
//
// インターフェース
//
interface interface1 {
        void message1();
}
//
// クラス
//
class super_class {
        public void message2() {
                System.out.println("super_class.message2");
        }
}
//
class class1 extends super_class implements interface1 {
        public void message1() {
                System.out.println("class1.message1");
        }
}
//
class class2 implements interface1 {
        public void message1() {
                System.out.println("class2.message1");
        }
}
public class implements_test {
        public static void main(String[] args) {
                interface1 ip1 = new class1();
                interface1 ip2 = new class2();
                ip1.message1();
                ip2.message1();
        }
}

インターフェース(interface1)で宣言された変数 ip1, ip2には、同じインターフェースをインプリメントしたクラス(class1, class2)から生成したオブジェクトであれば何でも格納できる。

正直、現時点ではそのメリットを理解できてるとは言い難い。まぁ有る程度の経験値を積めば、有る日いきなり雲が晴れたかのように理解できる事もあろうか...。

implements_test.java - 実行結果

class1.message1
class2.message1

thread_test.java - スレッド

//
// 「thread」テスト
//
// compile : javac -encoding utf-8 thread_test.java
// run     : java -cp . thread_test
//
import java.io.*;

public class thread_test {
	public static void main(String[] args) {
		called_thread ct = new called_thread("first_arg", "second_arg");
		ct.start();

		called_thread2 ct2 = new called_thread2("first_arg", "second_arg");
		Thread th = new Thread(ct2);
		th.start();

		try {
			ct.join(); // ctスレッドの終了を待つ
			th.join(); // thスレッドの終了を待つ
		catch (InterruptedException e){
			System.out.println("join fail : " + e);
		}
	}
}

class called_thread extends Thread {
//
// インスタンス変数(引数の受け皿)
//
	String arg1, arg2;
//
// コンストラクタ(引数受け取り)
//
	called_thread(String arg1, String arg2){
		this.arg1 = arg1;
		this.arg2 = arg2;
	}
//
// スレッド処理の本体
//
	public void run (){
		System.out.println("called_thread with arg1 = " + arg1 + ", arg2 = " + arg2);
	}
}

class called_thread2 /* extends hoge */ implements Runnable {
//
// インスタンス変数(引数の受け皿)
//
	String arg1, arg2;
//
// コンストラクタ(引数受け取り)
//
	called_thread2(String arg1, String arg2){
		this.arg1 = arg1;
		this.arg2 = arg2;
	}
//
// スレッド処理の本体
//
	public void run (){
		System.out.println("called_thread2 with arg1 = " + arg1 + ", arg2 = " + arg2);
	}
}

thread_test.java - 実行結果

called_thread with arg1 = first_arg, arg2 = second_arg
called_thread2 with arg1 = first_arg, arg2 = second_arg

thread_sync_test.java - スレッド

//
// 「thread(synchronized)」テスト
//
// compile : javac -encoding utf-8 thread_sync_test.java
// run     : java -cp . thread_sync_test
//
import java.io.*;

public class thread_sync_test {
	public static void main(String[] args){
		called_thread[] ct = new called_thread[10];
		counter cnt_non_threadsafe = new counter_non_threadsafe();
		counter cnt_threadsafe = new counter_threadsafe();

		//
		// NON thread safe section
		//
		for (int i = 0; i < 10; i++){
			ct[i] = new called_thread(cnt_non_threadsafe);
			ct[i].start();
		}

		try {
			for (int i = 0; i < 10; i++){
				ct[i].join();
			}
		}catch (InterruptedException e){
			System.out.println("join fail :  " + e);
		}

		System.out.println("non thread safe counter = " + cnt_non_threadsafe.get());

		//
		// thread safe section
		//
		for (int i = 0; i < 10; i++){
			ct[i] = new called_thread(cnt_threadsafe);
			ct[i].start();
		}

		try {
			for (int i = 0; i < 10; i++){
				ct[i].join();
			}
		}catch (InterruptedException e){
			System.out.println("join fail :  " + e);
		}

		System.out.println("thread safe counter = " + cnt_threadsafe.get());
	}
}

interface counter {
	void up();
	int get();
}

class counter_non_threadsafe implements counter {
	int data;
	void counter_non_threadsafe(){
		data = 0;
	}
	public /* synchronized */ void up(){
		int tmp;

		tmp = data;
		try {
			Thread.sleep(1000);
		}catch (InterruptedException e){
			System.out.println("sleep fail :  " + e);
		}
		data = tmp + 1;
	}
	public int get(){
		return data;
	}
}

class counter_threadsafe implements counter {
	int data;
	void counter_threadsafe(){
		data = 0;
	}
	public synchronized void up(){
		int tmp;

		tmp = data;
		try {
			Thread.sleep(1000);
		}catch (InterruptedException e){
			System.out.println("sleep fail :  " + e);
		}
		data = tmp + 1;
	}
	public int get(){
		return data;
	}
}

class called_thread extends Thread {
//
// インスタンス変数(引数の受け皿)
//
	counter cnt;
//
// コンストラクタ(引数受け取り)
//
	called_thread(counter cnt){
		this.cnt = cnt;
	}
//
// スレッド処理の本体
//
	public void run (){
		System.out.println("run called_thread");
		cnt.up();
	}
}

thread_sync_test.java - 実行結果

run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
non thread safe counter = 1
run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
thread safe counter = 10

thread_waitnotify_test.java - スレッド

//
// 「thread(wait, notify)」テスト
//
// compile : javac -encoding utf-8 thread_waitnotify_test.java
// run     : java -cp . thread_waitnotify_test
//
import java.io.*;
//
// メインクラス
//
public class thread_waitnotify_test {
	public static void main(String[] args){
		called_thread[] ct = new called_thread[10];
		counter cnt = new counter(0 /* カウンターの初期値 */, 1 /* 同時アクセス可能スレッド数 */);
		//
		// スレッドの起動
		//
		for (int i = 0; i < ct.length; i++){
			ct[i] = new called_thread(cnt);
			ct[i].start();
		}
		//
		// スレッド終了の待ち合わせ
		//
		try {
			for (int i = 0; i < ct.length; i++){
				ct[i].join();
			}
		}catch (InterruptedException e){
			System.out.println("join fail :  " + e);
		}

		System.out.println("thread safe counter = " + cnt.get());
	}
}
//
// wait(), notifyAll(), セマフォ変数(sem)を利用した、同時アクセス可能スレッド数を指定した
// lock(), unlock()メソッドを持つcounterクラス
//
class counter {
	int init_sem, sem;
	int data;
	//
	// コンストラクタ(カウンタの初期値、同時アクセスを許すスレッド数)
	//
	counter(int data, int sem){
		this.data = data;
		init_sem = this.sem = sem;
	}
	//
	// ロックメソッド
	//
	synchronized void lock(){
		if (sem <= 0){
			try {
				while (sem <= 0){
					wait();
				}
				sem--;
			}catch (InterruptedException e){
				System.out.println("wait fail :  " + e);
			}
		}else{
			sem--;
		}
	}
	//
	// アンロックメソッド
	//
	synchronized void unlock(){
		if (sem < init_sem){
			sem++;
			notifyAll();
		}
	}
	//
	// カウントアップメソッド
	//
	//    lock(),unlock()で排他制御を行うので、あえてsynchronized修飾していない
	//
	void up(){
		int tmp;

		tmp = data;
		try {
			Thread.sleep(1000);
		}catch (InterruptedException e){
			System.out.println("sleep fail :  " + e);
		}
		data = tmp + 1;
	}
	//
	// カウンター値取得
	//
	int get(){
		return data;
	}
}
//
// スレッドの本体クラス
//
class called_thread extends Thread {
	//
	// インスタンス変数(引数の受け皿)
	//
	counter cnt;
	//
	// コンストラクタ(引数受け取り)
	//
	called_thread(counter cnt){
		this.cnt = cnt;
	}
	//
	// スレッド処理の本体
	//
	public void run (){
		System.out.println("run called_thread");
		cnt.lock();
		cnt.up();
		cnt.unlock();
	}
}

thread_waitnotify_test.java - 実行結果

run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
run called_thread
thread safe counter = 10

tcpip_client.java - TCP/IPクライアント

//
// 「tcp/ip クライアント」テスト
//
// compile : javac -encoding utf-8 tcpip_client.java
// run     : java -cp . tcpip_client
//
import java.io.*;
import java.net.*;

public class tcpip_client {
	public static void main(String[] args) throws IOException {
//
//          throws IOException => 自分を呼び出したメソッドに例外処理を委譲する。
//
		Socket           socket;
		BufferedReader   br;
		BufferedWriter   bw;
//
// サーバへ接続するためのソケットオープン
//
		socket = new Socket("localhost", 12345);
//
// サーバからの受信ストリーム開く(行アクセス)
//
		br  = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//
// サーバへの送信ストリーム開く(行アクセス)
//
		bw   = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//
// 送信電文の準備
//
		String outstr = "テスト電文です";
//
// サーバへ電文送信
//
		bw.write(outstr, 0, outstr.length());
//
// サーバへ改行送信
//
		bw.newLine();
//
// サーバへの送信を強制出力
//
		bw.flush();
//
// サーバからレスポンスを受信
//
		String instr;
		if ((instr = br.readLine()) == null){
			System.out.println("受信エラー");
		}else{
			System.out.println(instr);
		}
//
// ストリーム、ソケットを閉じる
//
		bw.close();
		br.close();
		socket.close();
	}
}

tcpip_server.java - TCP/IPサーバ(シングルサーバ)

//
// 「tcp/ip サーバ」テスト
//
// compile : javac -encoding utf-8 tcpip_server.java
// run     : java -cp . tcpip_server
//
import java.io.*;
import java.net.*;

public class tcpip_server {
	public static void main(String[] args) throws IOException {
		ServerSocket serverSocket;
		Socket socket;
		BufferedReader in;
		BufferedWriter out;
		String line;
//
// クライアントからの電文を受信するソケットを開く
//
		serverSocket = new ServerSocket(12345);
//
// 受信ループ
//
		while (true){
//
// クライアントからの受信を待つ & 送受信のためのソケットを得る
//
			socket = serverSocket.accept();
//
// クライアントからの受信ストリーム
//
			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//
// クライアントへの送信ストリーム
//
			out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//
// 送受信ループ
//
			while ((line = in.readLine()) != null){
				if (line.compareTo("END") == 0){
					break;
				}
//
// クライアントへ送信(echo backするだけ)
//
				out.write(line);
				out.newLine();
				out.flush();
			}
//
// ストリーム、ソケットを閉じる
//
			out.close();
			in.close();
			socket.close();
//
			if (line != null){
				if (line.compareTo("END") == 0){
					break;
				}
			}
		}
	}
}

tcpip_multi_server.java - TCP/IPサーバ(マルチスレッド)

//
// 「tcp/ip サーバ(マルチスレッド版)」テスト
//
// compile : javac -encoding utf-8 tcpip_multi_server.java
// run     : java -cp . tcpip_multi_server
//
import java.io.*;
import java.net.*;

public class tcpip_multi_server {
	public static void main(String[] args) throws IOException {
		ServerSocket serverSocket;
		Socket socket;
//
// クライアントからの電文を受信するソケットを開く
//
		serverSocket = new ServerSocket(12345);
//
// 受信ループ
//
		while (true){
//
// クライアントからの受信を待つ & 送受信のためのソケットを得る
//
			socket = serverSocket.accept();
//
// 送受信処理のためのスレッドを起動する。
// 起動されたスレッドはバックグラウンドで並行して実行される。
// ループの先頭に戻り次の受信を待つ。
//
			thread_main tm = new thread_main(socket);
			tm.start();
		}
	}
}
//
// 送受信クラス
//
class thread_main extends Thread {
//
// インスタンス変数(送受信ソケット)
//
	Socket socket;
//
// コンストラクタ(ソケット取得)
//
	thread_main (Socket socket){
		this.setDaemon(true);
		this.socket = socket;
	}
//
// スレッドの主処理
//
	public void run() {
		try {
//
// クライアントからの受信ストリーム
//
			BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//
// クライアントへの送信ストリーム
//
			BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//
// 送受信ループ
//
			String line;
			while ((line = in.readLine()) != null){
				if (line.compareTo("END") == 0){
					break;
				}
//
// クライアントへ送信(echo backするだけ)
//
				out.write(line);
				out.newLine();
				out.flush();
			}
//
// ストリーム、ソケットを閉じる
//
			out.close();
			in.close();
			socket.close();
		}catch (IOException e){
		}
	}
}

そう、後で知った事だが、Javaのクラス名称は大文字で始めるのが習慣らしい。上記のサンプルはそれを知る前に作ったので、クラス名称が全て小文字で始まっている。あしからず。

Package文

MyPackage/Package_test.java
package MyPackage;
public class Package_test {
        public void message (){
                System.out.println("MyPackage.Package_test is called");
        }
}

上記のソースは他人に配布して利用してもらう前提のパッケージである。

「package MyPackage」でパッケージ名を宣言し、同名のディレクトリにソースを作成する。

Package_main_test.java
import MyPackage.*;
public class Package_main_test {
        public static void main(String[] args){
                Package_test mp = new Package_test();
                mp.message();
        }
}

「MyPackage」を利用する場合は「import MyPackage.*;」で利用を宣言する。

Package文 - 実行結果

$ javac -encoding utf-8 MyPackage/Package_test.java
$ javac -encoding utf-8 Package_main_test.java
$ java Package_main_test
MyPackage.Package_test is called

パッケージを配布する場合は

$ jar cf MyPackage.jar MyPackage/

として「MyPackage.jar」を作成し、これを配布する。

配布された側では

$ java -cp .:MyPackage.jar Package_main_test

のように「-cp .:MyPackage.jar」を指定してして実行する。もしくは環境変数 CLASSPATHに設定して実行する。

main()を含み複数のclassから成るアプリケーションをjarにまとめて実行する

JarTest.java
public class JarTest {
	public static void main(String[] args) {
		JarTestSub jt = new JarTestSub();
		jt.hello();
	}
}

class JarTestSub {
	public void hello(){
		System.out.println("Hello.");
	}
}
jarファイル作成等

コンパイル

$ javac -encoding utf-8 JarTest.java
$ ls -al JarTest*class
-rw-r--r-- 1 m-ito m-ito 318  5月 30 12:22 JarTest.class
-rw-r--r-- 1 m-ito m-ito 393  5月 30 12:22 JarTestSub.class

jarファイル作成

$ jar cvf JarTest.jar JarTest.class JarTestSub.class
マニフェストが追加されました。
JarTest.class を追加中です。(入 = 318) (出 = 239)(24% 収縮されました)
JarTestSub.class を追加中です。(入 = 393) (出 = 279)(29% 収縮されました)
$ ls -al JarTest.jar
-rw-r--r-- 1 m-ito m-ito 1105  5月 30 12:23 JarTest.jar

マニフェストファイル取り出しのためにjarファイルを展開する

$ jar xvf JarTest.jar
  META-INF/ が作成されました。
 META-INF/MANIFEST.MF が展開されました。
 JarTest.class が展開されました。
 JarTestSub.class が展開されました。

マニフェストファイルにMain-Classの指定を追加する

$ vi META-INF/MANIFEST.MF
Main-Class: JarTest
$ cat META-INF/MANIFEST.MF
Manifest-Version: 1.0
Created-By: 1.6.0_43 (Sun Microsystems Inc.)
Main-Class: JarTest

jarファイルにマニフェストファイルを加えて再作成する

$ jar cvfm JarTest.jar META-INF/MANIFEST.MF JarTest.class JarTestSub.class
マニフェストが追加されました。
JarTest.class を追加中です。(入 = 318) (出 = 239)(24% 収縮されました)
JarTestSub.class を追加中です。(入 = 393) (出 = 279)(29% 収縮されました)

実行してみる

$ java -jar JarTest.jar
Hello.

[追記]jarファイルの実行の別解

mainメソッドを含むMainクラスとその他もろもろのクラスをまとめて、Main.jarを作成したとする。

$ jar cf Main.jar Main.class Hoge1.class Hoge2.class ...

Main.jarが別のFoo1.jar、Foo2.jar、Foo3.jarに依存するとした場合、Main.jarは以下のように実行する。

$ java -cp Foo1.jar:Foo2.jar:Foo3.jar:Main.jar Main

java -cp {依存するjar}:...:{依存するjar}:{mainメソッドを含むjar} {mainメソッドを含むクラス名}

また、マニフェストファイルに、

Class-Path: Foo1.jar:Foo2.jar:Foo3.jar
Main-Class: Main

を追記して、Main.jarを作成すれば、

$ java -jar Main.jar

で実行できる。

io_test.java - 入出力関係の今一度のまとめ...

//
// 「Input/Output全般」テスト
//
// compile : javac -encoding utf-8 io_test.java
// run     : java -cp . io_test
//
import java.io.*;

public class io_test {
	public static void main(String[] args) throws Exception {
//============================================================
// Output
//============================================================
//------------------------------------------------------------
// DataOutputStream
//------------------------------------------------------------
//
// o バイナリデータの出力を行う
// o 出力するデータは byte配列、int、long 等の基本型
//
//		OutputStream os = socket.getOutputStream();	// ソケットへ出力
//		OutputStream os = process.getOutputStream();	// プロセスのstdinへ出力
//		OutputStream os = System.out;	// stdoutへ出力
//
		OutputStream os = new FileOutputStream("io_test_dos.dat");	// ファイルへ出力

		DataOutputStream dos = new DataOutputStream(os);
		byte[] b = new byte[10];
		b[0] = 0;
		b[1] = 1;
		b[2] = 2;
		dos.write(b, 0, 3);
		dos.writeByte(3);
		dos.writeInt(4);
		dos.flush();
		dos.close();

//------------------------------------------------------------
// OutputStreamWriter
//------------------------------------------------------------
//
// o テキストデータの出力を行う
// o 出力するデータはStringオブジェクト
// o 文字コード変換が行われる
//
// 実際のコーディング中では(下記の)BufferedWriterでラップして利用するのが
// 望ましい。
//
		os = new FileOutputStream("io_test_osw.txt");

		OutputStreamWriter osw = new OutputStreamWriter(os, "EUC_JP");
		String s = "文字列desu";
		osw.write(s);
		osw.write("\n");
		osw.write(s, 2, 3);
		osw.write("\n");
		osw.flush();
		osw.close();

//------------------------------------------------------------
// BufferedWriter
//------------------------------------------------------------
//
// o テキストデータの出力を行う
// o 出力するデータはStringオブジェクト
// o 文字コード変換が行われる
// o 出力は適切にバッファリングされる
//
		os = new FileOutputStream("io_test_bw.txt");

		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os, "EUC_JP"));
		bw.write(s);
		bw.newLine();
		bw.write(s, 2, 3);
		bw.newLine();
		bw.flush();
		bw.close();

//------------------------------------------------------------
// PrintStream
//------------------------------------------------------------
//
// o テキストデータの出力を行う
// o 出力するデータをフォーマット可能
// o 文字コード変換が行われる
// o 出力は適切にバッファリングされる
//
		os = new FileOutputStream("io_test_ps.txt");

		boolean auto_flush = true;
		PrintStream ps = new PrintStream(os, auto_flush, "EUC_JP");
		ps.printf("%s\n", s);
		ps.flush();
		ps.close();

//============================================================
// Input
//============================================================
//------------------------------------------------------------
// DataInputStream
//------------------------------------------------------------
//
// o バイナリデータの入力を行う
// o 入力するデータは byte配列、int、long 等の基本型
//
//		InputStream is = socket.getInputStream();	// ソケットから入力
//		InputStream is = process.getInputStream();	// プロセスのstdoutから入力
//		InputStream is = process.getErrorStream();	// プロセスのstderrから入力
//		InputStream is = System.out;	// stdinから入力
//		InputStream is = System.err;	// stderrから入力
//
		InputStream is = new FileInputStream("io_test_dos.dat");	// ファイルから入力

		DataInputStream dis = new DataInputStream(is);
		byte[] dis_b_array = new byte[10];
		dis.read(dis_b_array, 0, 3);
		byte dis_byte = dis.readByte();
		int dis_int = dis.readInt();
		dis.close();

		System.out.println(String.format("dis_b_array[0] = %d", dis_b_array[0]));
		System.out.println(String.format("dis_b_array[1] = %d", dis_b_array[1]));
		System.out.println(String.format("dis_b_array[2] = %d", dis_b_array[2]));
		System.out.println(String.format("dis_byte = %d", dis_byte));
		System.out.println(String.format("dis_int = %d", dis_int));

//------------------------------------------------------------
// InputStreamReader
//------------------------------------------------------------
//
// o テキストデータの入力を行う
// o 入力するデータは char、char配列
// o 文字コード変換が行われる
//
// 実際のコーディング中では(下記の)BufferedReaderでラップして利用するのが
// 望ましい。
//
		is = new FileInputStream("io_test_osw.txt");

		InputStreamReader isr = new InputStreamReader(is, "EUC_JP");
		int isr_c;
		char[] isr_c_array = new char[10];
		isr_c = isr.read();
		isr.read(isr_c_array, 0, 3);
		isr.close();

		System.out.println(String.format("isr_c = %c", isr_c));
		System.out.println(String.format("isr_c_array[0] = %c", isr_c_array[0]));
		System.out.println(String.format("isr_c_array[1] = %c", isr_c_array[1]));
		System.out.println(String.format("isr_c_array[2] = %c", isr_c_array[2]));

//------------------------------------------------------------
// BufferedReader
//------------------------------------------------------------
//
// o テキストデータの入力を行う
// o 入力するデータは char、char配列、Stringオブジェクト
// o 文字コード変換が行われる
// o 入力は適切にバッファリングされる
// o 行入力が可能
//
		is = new FileInputStream("io_test_bw.txt");

		BufferedReader br = new BufferedReader(new InputStreamReader(is, "EUC_JP"));
		int br_c;
		char[] br_c_array = new char[10];
		br_c = br.read();
		br.read(br_c_array, 0, 3);
		String br_s = br.readLine();
		br.close();

		System.out.println(String.format("br_c = %c", br_c));
		System.out.println(String.format("br_c_array[0] = %c", br_c_array[0]));
		System.out.println(String.format("br_c_array[1] = %c", br_c_array[1]));
		System.out.println(String.format("br_c_array[2] = %c", br_c_array[2]));
		System.out.println("br_s = " + br_s);
	}
}

io_test.java - 実行結果

$ java io_test
dis_b_array[0] = 0
dis_b_array[1] = 1
dis_b_array[2] = 2
dis_byte = 3
dis_int = 4
isr_c = 文
isr_c_array[0] = 字
isr_c_array[1] = 列
isr_c_array[2] = d
br_c = 文
br_c_array[0] = 字
br_c_array[1] = 列
br_c_array[2] = d
br_s = esu
$ od -xc io_test_dos.dat
0000000  00  01  02  03  00  00  00  04
           0100    0302    0000    0400
         \0 001 002 003  \0  \0  \0 004
0000010
$ cat io_test_osw.txt
文字列desu
列de
$ cat io_test_bw.txt
文字列desu
列de
$ cat io_test_ps.txt
文字列desu

ThrowTest.java - 例外処理を行う

class MyException extends Exception {
        MyException(String msg){
                super(msg);
        }
}

class ThrowTest {
        public static void main(String[] args){
                ThrowTest m = new ThrowTest();
                try {
                        m.methodA();
                }catch (MyException e){
                        System.out.println(e);
                }finally{
                }
        }

        public void methodA() throws MyException {
                MyException e = new MyException("ERROR DESU!!");
                throw e;
        }
}

ThrowTest.java - 実行結果

MyException: ERROR DESU!!

その他もろもろ(未検証)

byte,char配列からStringへ変換
byte [] byte_arry = { 0x41, 0x42, 0x43 };
String str = new String(byte_arry);
// String str = new String(byte_arry, "UTF-8");
char [] char_arry = { 0x61, 0x62, 0x63 };
String str = new String(char_arry);
// String str = new String(char_arry, "US-ASCII");
Stringからbyte配列へ変換
String str = new String("abc");
byte [] byte_arry = str.getBytes();
// byte [] byte_arry = str.getBytes("UTF-8");

2009年06月14日 request_module[net-pf-10]: waitpid(3788,...) failed, errno 1 (その3) [長年日記]

_ request_module[net-pf-10]: waitpid(3788,...) failed, errno 1 (その3)

どう考えても、いきなりこんなメッセージが出始めるのはおかしい。ここしばらくHDの調子が悪く、何回もfsckのお世話になっていたから、どこか致命的な壊れ方をしているのかもしれない(/libあたり...)。

とりあえず、良い機会なので現在のSlackware-10.1からSlackware-11.0にバージョンアップを行った。

なぜ最新のSlackware-12.2でなく、11.0かというと、12.0系はカーネルが2.6系かつinitrd.imgの肥大により、メモリーが64MBのlibretto100ではloadlinによるブートが出来なくなっていた事と、11.0がカーネル2.4系の最終ディストリビューションであることによる。

結構いろんなサーバ機能を構築していたので、それらの再構築に結構てまどったが、良い頭の体操になった感じ。作業経過はブログやウェブページに残しておくもんですな。

オリジナルのカーネルバージョンが2.4.33.3だったので、2.4.37.1をビルド中。

あっ、もちろん変なエラーメッセージは出なくなったよう。


2009年06月15日 request_module[net-pf-10]: waitpid(3788,...) failed, errno 1 (その4) [長年日記]

_ request_module[net-pf-10]: waitpid(3788,...) failed, errno 1 (その4)

2.4.37.1をビルドしたらまた出た。一度オリジナルの2.4.33.3のコンフィグから make oldconfig して様子を見てみよう。

_ JVim 3.0-j2.1a の画面分割(split)

いまだに古いJvim(3.0-j2.1a)を使ってるのだけれども、今さらながら画面分割出来る事に気づいたのでメモする。

  • :split ファイル名 : 分割したウインドウで指定したファイルを開く
  • CTRL-W s : 今編集しているファイルを分割しウインドウで表示する
  • CTRL-W n : 分割して空のウインドウを開く
  • CTRL-W q : ウインドウを閉じ、編集を終了する
  • CTRL-W c : ウインドウを閉じる
  • CTRL-W o : 分割を中止し、現在編集中のファイルのみ表示する
  • CTRL-W j : 下のウインドウに移動する
  • CTRL-W k : 上のウインドウに移動する
  • CTRL-W CTRL-W : 次のウインドウに移動する(ローテート)
  • CTRL-W = : 各ウインドウの高さをそろえる
  • CTRL-W - : ウインドウの高さを低くする
  • CTRL-W + : ウインドウの高さを高くする

関連してバッファー操作

  • :buffers or :files : 編集中バッファー一覧表示
  • :buffer バッファ番号 : 指定バッファ表示
  • :bnext : 次のバッファ表示
  • :bprevious : 前のバッファー表示

_ request_module[net-pf-10]: waitpid(3788,...) failed, errno 1 (その5)

オリジナルの2.4.33.3のコンフィグから make oldconfig してもメッセージ出た...。Slackware-11.0にアップデートしたのはこの件に関しては意味無かったか。まぁ前のシステムはfsckかかりまくりだったので良い機会だったと納得しよう。

エラーメッセージに関しては2.4.37.1に固有の問題かもしれない。syslogのディスクアクセスは気になるところだが、それ以外は問題なさそうなので、ひとまず様子見としよう。


2009年06月18日 request_module[net-pf-10]: waitpid(3788,...) failed, errno 1 (その6) [長年日記]

_ request_module[net-pf-10]: waitpid(3788,...) failed, errno 1 (その6)

request_module[net-pf-10]: waitpid(3788,...) failed, errno 1

の errno 1 は /usr/include/asm/errno.h より

#define EPERM            1      /* Operation not permitted */

を表していると思っていた。ところが /usr/src/linux/kernel/kmod.c より

  178  int request_module(const char * module_name)
  179  {
  180          pid_t pid;
  181          int waitpid_result;
  182          sigset_t tmpsig;
  183          int i;
  184          static atomic_t kmod_concurrent = ATOMIC_INIT(0);
  185  #define MAX_KMOD_CONCURRENT 50  /* Completely arbitrary value - KAO */
  186          static int kmod_loop_msg;
  187
  188          /* Don't allow request_module() before the root fs is mounted!  */
  189          if ( ! current->fs->root ) {
  190                  printk(KERN_ERR "request_module[%s]: Root fs not mounted\n",
  191                          module_name);
  192                  return -EPERM;
  193          }
  194
  195          /* If modprobe needs a service that is in a module, we get a recursive
  196           * loop.  Limit the number of running kmod threads to max_threads/2 or
  197           * MAX_KMOD_CONCURRENT, whichever is the smaller.  A cleaner method
  198           * would be to run the parents of this process, counting how many times
  199           * kmod was invoked.  That would mean accessing the internals of the
  200           * process tables to get the command line, proc_pid_cmdline is static
  201           * and it is not worth changing the proc code just to handle this case.
  202           * KAO.
  203           */
  204          i = max_threads/2;
  205          if (i > MAX_KMOD_CONCURRENT)
  206                  i = MAX_KMOD_CONCURRENT;
  207          atomic_inc(&kmod_concurrent);
  208          if (atomic_read(&kmod_concurrent) > i) {
  209                  if (kmod_loop_msg++ < 5)
  210                          printk(KERN_ERR
  211                                 "kmod: runaway modprobe loop assumed and stopped\n");
  212                  atomic_dec(&kmod_concurrent);
  213                  return -ENOMEM;
  214          }
  215
  216          pid = kernel_thread(exec_modprobe, (void*) module_name, 0);
  217          if (pid < 0) {
  218                  printk(KERN_ERR "request_module[%s]: fork failed, errno %d\n", module_name, -pid);
  219                  atomic_dec(&kmod_concurrent);
  220                  return pid;
  221          }
  222
  223          /* Block everything but SIGKILL/SIGSTOP */
  224          spin_lock_irq(&current->sigmask_lock);
  225          tmpsig = current->blocked;
  226          siginitsetinv(&current->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP));
  227          recalc_sigpending(current);
  228          spin_unlock_irq(&current->sigmask_lock);
  229
  230          waitpid_result = waitpid(pid, NULL, __WCLONE);
  231          atomic_dec(&kmod_concurrent);
  232
  233          /* Allow signals again.. */
  234          spin_lock_irq(&current->sigmask_lock);
  235          current->blocked = tmpsig;
  236          recalc_sigpending(current);
  237          spin_unlock_irq(&current->sigmask_lock);
  238
  239          if (waitpid_result != pid) {
  240                  printk(KERN_ERR "request_module[%s]: waitpid(%d,...) failed, errno %d\n",
  241                         module_name, pid, -waitpid_result);
  242          }
  243          return 0;
  244  }

240行〜241行が問題のエラーメッセージを出しているところなのだが、errnoに該当するのは -waitpid_result で、これは230行の waitpidのリターン値(-1)を符号反転したものに過ぎない。waitpidのリターン値が-1なのは単に「エラーで返ったよ」の印に過ぎず、真のエラーコードは errno に格納されているはず。なので、

  239          if (waitpid_result != pid) {
  240  #if 0
  241                  printk(KERN_ERR "request_module[%s]: waitpid(%d,...) failed, errno %d\n",
  242                         module_name, pid, -waitpid_result);
  243  #else
  244                  printk(KERN_ERR "request_module[%s]: waitpid(%d,...) failed, errno %d realerrno %d\n",
  245                         module_name, pid, -waitpid_result, errno);
  246  #endif
  247          }

のようにして、カーネルをビルド中。

_ request_module[net-pf-10]: waitpid(3788,...) failed, errno 1 (その7)

本当の errno は

ECHILD 10 /* No child processes */

だった。

2.4系のスレッドの問題かもしれないが、はっきりとした事は言えない。とりあず

*** kernel/kmod.c.ORG   2009-06-18 01:09:00.000000000 +0900
--- kernel/kmod.c       2009-06-18 09:56:55.000000000 +0900
***************
*** 237,244 ****
--- 237,251 ----
        spin_unlock_irq(&current->sigmask_lock);

        if (waitpid_result != pid) {
+ #if 0
                printk(KERN_ERR "request_module[%s]: waitpid(%d,...) failed, errno %d\n",
                       module_name, pid, -waitpid_result);
+ #else
+               if (errno != ECHILD){
+                       printk(KERN_ERR "request_module[%s]: waitpid(%d,...) failed, errno %d realerrno %d\n",
+                              module_name, pid, -waitpid_result, errno);
+               }
+ #endif
        }
        return 0;
  }

みたいにして、ECHILDの時はメッセージを出さないようにした。ビルド&再起動して様子をみているけれど、非常に場当たり的だが問題なさそう。


2009年06月19日 GARP(Gratuitous ARP) [長年日記]

_ GARP(Gratuitous ARP)

今日、初めて知った。自身のIPアドレス対応するMACアドレスを問い合わせるARPのことをGARP(Gratuitous ARP)というらしい。

自分に関する事を問い合わせるARPパケットに意味が有るのかと思うが、

  • IPアドレスのダブリをチェックしたり(別の場所から自分自身が返事したら恐いわな)
  • 他ノードの持つARPテーブル内の自身の情報を強制的に更新させる

という意味がある。

_ request_module[net-pf-10]: waitpid(3788,...) failed, errno 1 (その8)

カーネルソースの書き換え(kernel/kmod.c)により、無理矢理エラーメッセージを出なくして、強引に解決させたと思われた、この一件。実は以下のような状況が発生していた。

501 m-ito@lib100 /home/m-ito> ps ax|egrep defunct
 1276 ?        Z      0:00 [modprobe.old] <defunct>
 1411 ?        Z      0:00 [modprobe.old] <defunct>
13756 ?        Z      0:00 [modprobe.old] <defunct>
13815 ?        Z      0:00 [modprobe.old] <defunct>
 7973 ?        Z      0:00 [modprobe.old] <defunct>
14710 ?        Z      0:00 [modprobe.old] <defunct>
15028 ?        Z      0:00 [smtp_wrapper] <defunct>
15153 pts/3    S+     0:00 egrep defunct
502 m-ito@lib100 /home/m-ito>

modprobe.oldがいわゆるゾンビプロセスになっている。つまり、正しくwaitpid()が機能していないという、あの状況にはっきりと呼応する。

503 m-ito@lib100 /home/m-ito> pstree -p|egrep modprobe.old
        |-named(7972)---modprobe.old(7973)
        |-ntpd(1409)---modprobe.old(1411)
        |-sshd(1274)-+-modprobe.old(1276)
        |            |-sshd(13755)-+-modprobe.old(13756)
        |            |-sshd(13814)-+-modprobe.old(13815)
        |            `-sshd(14709)-+-modprobe.old(14710)
504 m-ito@lib100 /home/m-ito>

named, ntpd, sshd は /usr/local/ 配下にあるのだけれど、Slackware-10.1から11.0にアップデートしたときには、リコンパイルせずに、既存の /usr/local/ をそのまま引き継いだ。

それが原因かと考え、とりあえずnamedをリコンパイルしてみたけれど、状況は変わらなかった。

心配の種は尽きまじ...

_ ruby(1.8.x)儂(わし)的解釈によるメモ(OSコマンドインジェクション対策)

シェルに渡す(外部から入力された)パラメータに関して、特殊文字とか、ややこしいことは考えずに全ての文字に対して、1文字ずつエスケープを行う。

#! /usr/bin/ruby
input = "test5.rb';`echo CRACKED`; echo '\\"
input.gsub!(/(.)/){'\\' + $1}
command = "echo #{input}"
p command
system(command)
"echo \\t\\e\\s\\t\\5\\.\\r\\b\\'\\;\\`\\e\\c\\h\\o\\ \\C\\R\\A\\C\\K\\E\\D\\`\\;\\ \\e\\c\\h\\o\\ \\'\\\\"
test5.rb';`echo CRACKED`; echo '\

これで良くないだろうか?


2009年06月23日 Unable to handle kernel paging request at virtual address ... etc [長年日記]

_ Unable to handle kernel paging request at virtual address ... etc

lib100サーバにまたヤバゲなメッセージが残されている。

Jun 22 17:16:59 lib100 kernel: Unable to handle kernel paging request at virtual address 655f22b7
Jun 22 17:16:59 lib100 kernel:  printing eip:
Jun 22 17:16:59 lib100 kernel: c0142200
Jun 22 17:16:59 lib100 kernel: *pde = 00000000
Jun 22 17:16:59 lib100 kernel: Oops: 0000
Jun 22 17:16:59 lib100 kernel: CPU:    0
Jun 22 17:16:59 lib100 kernel: EIP:    0010:[<c0142200>]    Not tainted
Jun 22 17:16:59 lib100 kernel: EFLAGS: 00210246
Jun 22 17:16:59 lib100 kernel: eax: 655f228b   ebx: c3ffec20   ecx: 00008000   edx: 00000000
Jun 22 17:16:59 lib100 kernel: esi: ffffffe2   edi: 00008001   ebp: c158df84   esp: c158df50
Jun 22 17:16:59 lib100 kernel: ds: 0018   es: 0018   ss: 0018
Jun 22 17:16:59 lib100 kernel: Process ruby (pid: 21691, stackpage=c158d000)
Jun 22 17:16:59 lib100 kernel: Stack: 00000000 00000000 00000004 c04e3ca0 00008000 c198e000 400d23e0 bffee0ac
Jun 22 17:16:59 lib100 kernel:        c0136ebe c198e000 00008001 000001b6 c158df84 c04e3ca0 c10c52e0 400d23e0
Jun 22 17:16:59 lib100 kernel:        c0140b0a 00000006 00000001 00000001 00000006 00000006 c013725b c198e000
Jun 22 17:16:59 lib100 kernel: Call Trace:    [<c0136ebe>] [<c0140b0a>] [<c013725b>] [<c0108963>]
Jun 22 17:16:59 lib100 kernel:
Jun 22 17:16:59 lib100 kernel: Code: f6 40 2c 01 0f 84 ec fc ff ff f7 c7 02 00 00 00 0f 84 e0 fc

メモリーの障害か、swapエリアのI/O error辺りか...と思い、予備のメモリと交換して、mkswap -c /dev/hda?でもするかと考えてた矢先に、このtDiaryが...

Plugin Error

Errors in plugins? Retry to Update or Configure.

    TDiary::PluginError

    Plugin error in '50sp.rb'.
    Plugin error in 'misc/plugin/amazon.rb'.
    Input/output error - /usr/lib/ruby/1.8/rexml/xpath_parser.rb
    (plugin/50sp.rb):129:in `load_plugin'

みたいなエラーを表示して動かなくなっていた。 /usr/lib/ruby/1.8/rexml/xpath_parser.rb を cat で表示させると

cat: /usr/lib/ruby/1.8/rexml/xpath_parser.rb: Input/output error

確かにI/O error状態で、さらに

# ls -al  /usr/lib/ruby/1.8/rexml/xpath_parser.rb
-rw-r--r-- 1 root root 3364114146225291585 1993-12-03 08:59 /usr/lib/ruby/1.8/rexml/xpath_parser.rb

と、脅威のファイルサイズを表示してくれた。ファイルの中身を確認すると、末尾に延々と NULL がくっついている感じ。

mv xpath_parser.rb xpath_parser.rb.ORG
cat xpath_parser.rb.ORG >xpath_parser.rb

catではきっちり32KByte読み出したところで I/O Error発生。

vi xpath_parser.rb

にて xpath_parser.rb のおケツにくっついた NULL を削除したら tDiary は復活した。後は、 fsck をかけて、超巨大な xpath_parser.rb.ORG がどうなるかだな。

それと、気になるのは

Unable to handle kernel paging request at virtual address

-rw-r--r-- 1 root root 3364114146225291585 1993-12-03 08:59 /usr/lib/ruby/1.8/rexml/xpath_parser.rb

の関係。鶏が先か、卵が先なのか...。

_ Unable to handle kernel paging request at virtual address ... etc(2)

fsckをかけてみると、やはりボコボコと修復されていった。そして、超巨大ファイルもグッとシュリンクされていた。少しは末尾に NULL が残っていたが。

不安は山盛りだがとりあえずこの状態で様子を見てみる。


2009年06月28日 Libretto U100/190DSB [長年日記]

_ Libretto U100/190DSB and Slackware-12.2

lib100(myh.no-ip.org)サーバの方は、超巨大ファイルをfsckにて消しさってからは、すこぶる調子がよろしい。

さて、家ではlib100サーバの予備機を24時間365日起動のfirefox専用端末として利用してきたのだけれど、さすがにクライアントとして動かすにはキツイと感じ始めた。

そこで、今流行のNetBookとやらをヤフオクで調査してみた。とりあえず東芝からはNB100という機種が出ているよう。値段的には4万円前後というところ。またどうでもいいことだが、型番に100が付くという所に親近感をおぼえる。

そんなことで、かなりNB100に気持が傾いていたのだが、たまたまLibretto U100という機種も何台かオークションに出品されていた。もちろんLibrettoシリーズ最後(?)の機種(でかつ型番に100が付く!)という事は知っていたし、発売当時(2005年ごろ)、20万円程度していて、とても手が出なかったという記憶があるのだが、この機種も3〜4万円程度で落札されている。

とはいえ4年程昔の機種なので、最新のNB100と比べれば見劣りするかと思ったのだが、DVD-RWに対応したドライブも付属しているし、CPUの性能もNB100atom(1.6GHz)に対してU100pentium-M(1.1GHz)は、互格らしい(atom 1.6GHzはCeleron 800〜900MHz程度)。もちろん消費電力では圧倒的にatomの方が有利なのだが、全体の消費電力に占める割合はハードディスクや液晶のバックライトの占める割合の方が大きいので、あまり差がでない。まして、自分的な使い方としては、あくまで24時間起動の自宅firefox端末なので、バッテリーの持ちはあまり気にする必要が無い。

それと、何も考えずにブートデバイスとして利用できる光学ドライブが付属するという点は、Linuxをインストールする上で非常にやりやすい。この点はLibretto100で苦労した事から考えると非常に魅力的だ。そういう周辺機器の点で、NB100NetBookという性格上どうしても切り捨てざるをえない。

...というような事を総合的に判断し U100落札しちゃいました。結局4万円をちょっと越えました(^^;。

_ 再パーティショニング

さて、落札後の取り引きもスムーズに進み、入金の翌日にブツは到着。しばらくプレインストールのMS-Windows XPをいじってみるも、迷子になったような気分に襲われ、やっぱりLinux(Slackware-12.2)を入れる。ただし、今回は家族も使うので、プレインストールのMS-Windows XPも残して、デュアルブートにしようと思う。

ともかく作業を始める前に「困ったときは Q&A」の「P.48 4 システム復元ツールのバックアップをとる」に従いシステムリカバリDVDとクイックプレイリカバリCDを作成した。その後、「P.83 2 ハードディスクから復元する」に従ってXPのパーティションを縮小して再インストールするのだが、その前にSlackware-12.2のインストールCDで起動してパーティションを切り直しておく。

切り直す前

Disk /dev/hda: 59.8 GB, 59814236160 bytes
255 heads, 63 sectors/track, 7272 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0xe2d9e2d9

   Device Boot      Start         End      Blocks   Id  System
/dev/hda1   *           1        6882    55279633    7  HPFS/NTFS
/dev/hda2            6883        7271     3124642+  1c  Hidden W95 FAT32 (LBA)

切り直した後

Disk /dev/hda: 59.8 GB, 59814236160 bytes
255 heads, 63 sectors/track, 7272 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0xe2d9e2d9

   Device Boot      Start         End      Blocks   Id  System
/dev/hda1   *           1        3395    27270306    7  HPFS/NTFS
/dev/hda2            3396        3520     1004062+  82  Linux swap
/dev/hda3            3521        6882    27005265   83  Linux
/dev/hda4            6883        7271     3124642+  1c  Hidden W95 FAT32 (LBA)

元々の/dev/hda2がリカバリ領域なので、それを間違わずに/dev/hda4に再割り当てすること。その後、0(ゼロ)キーを押しながら電源を投入し復元システムが起動したら、「2 パーティションサイズを変更せずに復元」を実行する。

_ Slackware-12.2のインストール

インストールそのものは何も問題ない。普通のノートパソコンと何も変わらない。光学ドライブのありがたみがしみる。

ここからは、細かい部分でのポイントを少し...

_ 内蔵無線LAN(ath5k Atheros AR2414)の設定

最初、/etc/rc.d/rc.wireless.confの方を有効にして設定していたのだが、インタフェース(wlan0)を認識し、自分自身にはpingが飛ぶものの、外部には継らない状況だった。結局、/etc/rc.d/rc.wireless.confの方は触る必要は無く(有効にする必要すら無い)、/etc/rc.d/rc.inet1.confの方に

## Config information for wlan0:
IFNAME[4]="wlan0"
IPADDR[4]="192.168.0.190"
NETMASK[4]="255.255.255.0"
USE_DHCP[4]=""
WLAN_ESSID[4]=xxxxxxxxxxx  <- 伏せ字
WLAN_KEY[4]="xxxxxxxxxx"   <- 伏せ字
TEWAY="192.168.0.100"

の様に記述するだけでネットワークに接続できた。

_ xorg (X Window System)

標準でインストールされている /etc/X11/xorg.conf のModesに"1280x768"を追加するだけでもとりあえずは問題ない。ただしドライバはvesaを利用するので、多少速度の面で不満がある。

Libretto U100 xorg.confで検索すると専用ドライバ(i810)を利用した例がいくつも出て来る。これらをそのまま利用させていただいても良い。ただし、これらの例では SWCursor が有効になっているパターンが多く、その為DRI(Direct Rendering Infrastructure)が有効に出来ない点に注意が必要。おそらくこれらの報告がなされた時点のXでは、この指定が無ければマウスカーソルが正しく表示出来なかったのだろうが、Slackware-12.2のXは

X.Org X Server 1.4.2
Release Date: 11 June 2008
X Protocol Version 11, Revision 0

とのことで、SWCursorの指定は必要無いようだ。

結局、私は xorgsetupでは画面がブラックアウトしてしまうので、xorgconfigを利用してベースを作り、Libretto U100 xorg.confで検索されるページから

Modeline    "1280x768" 90 1280 1328 1552 1704 768 768 788 808 +hsync +vsync

の指定を拝借して設定した。結果としては DRI(Direct Rendering Infrastructure)も有効になり、xengineで8800rpm程度は出ている。