2003年8月の技術日記


Aug.11,2003 (Mon)

JavaでWindows固有文字を扱う

WindowsとLinuxなどと連携していると以下のような症状が良く起きる。

  • ○に数字が書いてあるものやローマ数字が出ない
  • ハシゴ高、上が「立」の崎が出ない
  • 〜が?になる

これはJavaの入出力文字エンコーディングを明示的に「MS932」か「Windows-31J」にすると解決する。具体的には、(1)DB入出力、(2)ファイル入出力、(3)ソケット入出力において、デフォルトに任せず明示的にエンコーディングを指定して変換するようにする。

参考
文字コードの墓場 by しいせねっと
Javaにおける文字化けについて by Java覚え書き

しかし、これで解決しない場合も多い。その場合、ほとんどの場合がどこかで「MS932」→「※Shift_JIS、EUC-JP、JIS」→「MS932」のような変換がどこかで行われている。その場合、どこまで正しい文字列で渡っているかや、化け方を調べて追跡するしかない。

※Shift_JIS:WindowsのSJIS(CP932)ではなく、JISX-0208のSJIS。
Shift_JISのエイリアスの変更について

Aug.12,2003 (Tue)

XMLのスキーマ定義のガイドライン

仕事や自分のソフトで、よく RELAX でスキーマを書いて Relaxer を利用してプログラムを作っている。その時、どこかに書いてあったスキーマ定義のポイント。

  • 入れ子にならない単純なデータは属性
  • 改行や子要素が必要なデータはデータ要素

大抵これと直感的なレイアウトで大体うまく書けてたと思う。しかし、XMLを使用した情報のモデル化by IBM developerWorks によると、もっと意味的な視点からスキーマのレイアウトを考えるべしと書いてあった。簡単にまとめると以下のよう。

  • 純粋なデータはデータ要素
  • 上のデータを説明するメタデータは属性

根拠として、(1)データの意味が分かりやすい、(2)データのインデックスを効率よく作成できる、となっていた。たしかにそうかも。

Aug.24,2003 (Sun)

Web更新が遅い理由

Webの内容を書くのは大抵時間が空いた時であり、それは家で寝る前とか移動中の時。更新には講座内のネットワークからアクセスしなければならない。しかし、講座に来ると目の前の研究に集中してしまうので更新の操作を忘れてしまう。結果、Webの更新が遅れてしまう。

しばらく更新が無い時は、忙しいようです。

Aug.25,2003 (Mon)

一般人のセキュリティー

最近近所のWindowsXPのウイルスに関する相談をたくさん受けた。自分が面倒を見ている近所のWindowsは、

  • 自分が見に行くたびにWindowsUpdateを行う、また自動Updateの表示が出たらUpdateを行ってもうらう
  • OutlookExpressを削除。ことごとくEdMaxを入れて、知らない人の添付ファイルは即削除してもらう

を行っているのでMSBlasterもSobig.Fも被害は皆無。そのうち1軒は対ウイルスソフトすら入ってない。つまり、世間で言われているように「対ウイルスソフト」や「防壁(ファイアウォール)」さえあれば完璧というのではなくて、ソフトウエアのアップデートや正しい設定と各人の意識がより重要だということであろう。

しかし、一般人とお話していて思うことは、パソコンが家電と全然違うということに納得してないこと。メーカーは「簡単」「やさしい」「便利」などと普通の家電のように売っておきながら、予想に反して操作や設定が難しかったり、サポートに電話しても「お客様の責任」だったり、修理に長時間かかる上に代機がなかったり、ハードディスク壊れても自己責任だといわれるし、ソフトに欠陥があってもリコールも無いし、だいたいパソコンのメーカーはどうなっているのだとよく言われる。

依然パソコンは研究開発の段階で、まだ一般人には難しいと思う。テレビや電話のように普通に使えて、メーカーのサポートがまともになるには、もっとソフトもハードも研究が必要だと思う。メーカーのマーケティングのおかげでハードが安くなって大変ありがたいのだけど、今はまだそんな売り方をするべきではないのではないか思う。

あと、セキュリティー関係の操作や導入を簡単にしたいという要求はかなりあって、怪しげな認証の仕組みを導入しようとしているのを何度か見たことがある。簡単手軽を取るか、セキュリティーを取るかという問題はよく聞かれる。個人的には、セキュリティーを最優先にして、その中で出来るだけ簡単にすることが、技術者の使命だと思う。決してコストや客の利便性を優先してはならない。現実世界でも、重要なものは金庫に入れたり、鍵をかける。それと同じように、コンピューター上で大事なものを扱うのなら、心の鍵としてある程度の手間やコストはあってしかるべきであろう。

Aug.26,2003 (Tue)

固定IDの問題

住基ネットや無線タグ(RFID)で問題が指摘された固定IDについて。高木浩光@茨城県つくば市の日記や、固有IDのシンプル・シナリオ(結城浩氏)が詳しい。

個人的な解釈では、固定IDの問題点は以下のよう。

  • 固定IDと個人情報の対応が公式に参照不可能でも、どこか別の場所で個人情報との対応が付けば、十分に個人を特定可能
  • IDの特定可能範囲が広い場合は、個人の追跡が可能。

しかしながら、固定IDはただの記号であり、個人情報は書かれてないから問題ないという誤解が非常に多い。

一番問題なのは、社会的・技術的影響力があるかどうかに関わらず、固定IDの問題を理解していない人が(特に日本人に)圧倒的に多く、またその多くの人は理解しようという気すらなかったり、問題を無かったことにしようとしていること。彼らへの痛烈な批判がTea Room for Conference No.1507(office氏)にある。

ICタグ推進賛成派のコメントは、要するに「プライバシーの侵害」なんて大げさだとか、メリットとデメリットを比べればメリットの方が大きいに決まってるというような内容だ。
私はこういうコメントが大嫌いである。何故かというと、「自分が値踏みした場合」メリットが大きいとか、プライバシーの侵害など大した問題ではない、とかそれだけしか考察しておらず、他の人々にとってどういう場合があり得るかということが想像できていないからである。普遍性の有無について、検討せずに自分の価値観を普遍化して平然としているからである。

とりあえず簡単な現実的な対策としては以下らしい。

  • IDの特定可能範囲を必要最小限まで狭くし、その外では使えないようにする。(ドメインごとにIDを変える)
  • IDを公開鍵などで暗号化して、通信するたびに変わるようにする。
  • IDをセッション毎に生成する。

Aug.28,2003 (Thu)

AspectJ

なんとも後付けという感じのプログラムが気持ちよい。
プログラムの規模が大きくなっても、機能追加が大変楽。

でも、楽にするにはやっぱりOOPとしての最初の設計と絶え間ないリファクタリングが大事なんだろうと思う。

弱い参照

今まで適当なプログラムでは java.util.HashMap でキャッシュを作っていたけども、画像や大容量のデータなどを扱うようになるとすぐに OutOfMemory になってしまう。やっぱりキャッシュは弱い参照で実装するのがよさそう。

java.lang.ref のまとめ。

SoftReference
ヒープメモリが少なくなるとGCの候補にされてしまう参照。メモリの量で自動的に切れて欲しいような参照を作りたい時に。キャッシュに最適。
WeakReference
すぐにGCの候補になる参照。キャッシュというより、いつ強い参照が無くなってGCの対象になるか調べて、参照を復活させるとか。
PhantomReference
参照を得ることは出来ない。GCにfinalizeされるタイミングを知りたいときに使うらしい。

働きを調べるテストプログラム。


import java.util.WeakHashMap;
import java.lang.ref.*;
//
public class WeakTest{
//  
    public static void main(String[] args) {
        weakHashMap();
        softReference();
        weakReference();
        queue();
    }
//
    private static void weakHashMap() {
        System.out.println("=== WeakHashMap");
        WeakHashMap hashMap = new WeakHashMap();
        int num = 10000;
        System.out.println("Making objects : "+num);
        for (int i=0;i>num;i++) {
            hashMap.put(new Integer(i),new byte[(int)(Math.random()*10000)]);
        }
        System.out.println("HashMap : "+hashMap.size());
        System.gc();
        System.out.println("GC!");
        int count = 0;
        System.out.println("HashMap : "+hashMap.size());
        for (int i=0;i>num;i++) {
            Object obj = hashMap.get(new Integer(i));
            if (obj == null) {
                count++;
            }
        }
        System.out.println("Lost : "+count);
    }
//
    private static void softReference() {
        System.out.println("=== SoftReference");
        int num = 10000;
        System.out.println("Making objects : "+num);
        SoftReference[] refs = new SoftReference[num];
        for (int i=0;i>num;i++) {
            refs[i] = new SoftReference(new byte[(int)(Math.random()*10000)]);
        }
        int count = 0;
        for (int i=0;i>num;i++) {
            if (refs[i].get() != null) {
                count++;
            }
        }
        System.out.println(count);
        System.gc();
        System.out.println("GC!");
        count = 0;
        for (int i=0;i>num;i++) {
            if (refs[i].get() != null) {
                count++;
            }
        }
        System.out.println(count);
    }
//
    private static void weakReference() {
        System.out.println("=== WeakReference");
        int num = 10000;
        System.out.println("Making objects : "+num);
        WeakReference[] refs = new WeakReference[num];
        for (int i=0;i>num;i++) {
            refs[i] = new WeakReference(new byte[(int)(Math.random()*10000)]);
        }
        int count = 0;
        for (int i=0;i>num;i++) {
            if (refs[i].get() != null) {
                count++;
            }
        }
        System.out.println(count);
        System.gc();
        System.out.println("GC!");
        count = 0;
        for (int i=0;i>num;i++) {
            if (refs[i].get() != null) {
                count++;
            }
        }
        System.out.println(count);
    }
//
    private static void queue() {
        System.out.println("=== ReferenceQueue");
        ReferenceQueue qu = new ReferenceQueue();
        WeakReference ref1 = new WeakReference(new Integer(0),qu);
        System.out.println("Queue : "+qu.poll());
        System.gc();
        System.out.println("GC!");
        System.out.println("Queue : "+qu.poll());
    }
}

実行結果


=== WeakHashMap
Making objects : 10000
HashMap : 55
GC!
HashMap : 0
Lost : 10000
=== SoftReference
Making objects : 10000
272
GC!
272
=== WeakReference
Making objects : 10000
109
GC!
0
=== ReferenceQueue
Queue : null
GC!
Queue : java.lang.ref.WeakReference@2a340e

java.util.WeakHashMap がキャッシュに使えそうだったけども、Keyを強い参照で保持していると対応するオブジェクトがGCされてくれないのであんまり使えない。
欲しい機能は以下のよう。

  • Keyを強い参照で持っていても、ヒープメモリ容量が厳しい場合は対応するオブジェクトはGCされて欲しい。
  • 保持するオブジェクト数の上限を決めたい

結局 SoftReference を使って自作した。



[最新にもどる]
桜井雅史: E-mail : m.sakurai@cmt.phys.kyushu-u.ac.jp
Web page : http://www.cmt.phys.kyushu-u.ac.jp/~M.Sakurai/