月曜日, 28 2 月 2005

Lint4jでソース検査
この記事をクリップ!
このエントリーをはてなブックマークに追加

Lint4jFindBugsと同じようなJavaプログラムソース内のバグの温床となる記述やパフォーマンス低下につながる部分を探し出して警告してくれるツールだ。
指摘される部分の記述そのものがエラーではないため修正しなくても動作はするがメンテナンス性やパフォーマンス向上のため修正することが推奨されている。
サンプルとして以下のプログラムを用意しLint4jで検査してみた。
package test;

public class test
{
  public static void main(String[] args)
  {
    String hello=new String("hello");

    System.out.println(hello);
  }
}
で、Lint4jを実行。
$ lint4j -v 5 -sourcepath . *
./test/test.java:7: (4): Unnecessary creation of a String from another String
./test/test.java:9: (4): Possible debug call "System.out.println" was detected
問題となる記述が2箇所見つかった。
一つ目はStringインスタンスを作るのに既に""を使ってるにも関わらずさらにnew Stringしているのが問題で、二つ目はデバッグ出力として推奨されないSystem.out.printlnを使っているのが問題なようだ。System.outはともかくStringのコンストラクタは確かに無駄な処理なのでLint4jの判断は正しいと思う。
実際のプロジェクトでも定期的にソースを検査し問題となる部分がないか調べるといいかもしれない。
Posted by tsujitako at 1:39 午前 in Java/

日曜日, 27 2 月 2005

rpm2cpioでファイルの取り出し
この記事をクリップ!
このエントリーをはてなブックマークに追加

RPMからプログラムをインストールすると手間が省けるがインストールパスが固定されているため任意のパスに配置することが出来ない。
また一つだけのファイルを取り出そうとしてもrpmコマンドを使うと全てのファイルがインストールされ既存の環境に影響を与えてしまう。
そういうときはrpm2cpioを使うと柔軟にパッケージ内のファイルを扱うことが可能だ。
rpm2cpioはRPMをcpioアーカイブに変換するコマンドなのでcpioに変換後、任意にディレクトリに展開すれば既存の環境を変更せずにファイルを取り出すことが出来る。
またrpm2cpioは標準出力にcpioアーカイブを出力するのでリダイレクトして保存するかパイプでcpioに渡す必要がある。
以下はパイプでcpioに渡した例。
$ rpm2cpio xxx.ppc.rpm | cpio -id
xxx blocks
これでカレントにパッケージ内のファイルが階層付きで展開される。
でも自分は大体ソースからインストールするのでこのコマンドほとんど使わないけど。
Posted by tsujitako at 2:24 午前 in Linux/

土曜日, 26 2 月 2005

おむかえ当初のリル
この記事をクリップ!
このエントリーをはてなブックマークに追加

このころはまだ背中にラインが入ってたなぁ。今は真っ白になっちゃったけど。
Posted by tsujitako at 3:04 午前 in フェレット/

金曜日, 25 2 月 2005

AMCファイルのフォーマット変換
この記事をクリップ!
このエントリーをはてなブックマークに追加

FOMAなどの携帯で採用されている3GPフォーマットの動画はffmpegを使用すればMPEG1など他のフォーマットの動画に変換することが可能だが、auの一部の携帯で採用されているAMCフォーマットの動画はffmpegではUnknown formatとなり変換ができない。
が、このAMCファイルはMPlayerに付属しているmencoderを使えばまがりなりにも変換可能になる。
まずはMPlayerを普通にインストールする。
$ ./configure
$ make
$ make install
make installが終わるとmplayerと同時にmencoderもインストールされているはず。
test.amcというAMCファイルをtest.mpgに変換するには以下のように入力する。
$ mencoder test.amc -o test.mpg -oac lavc -ovc lavc
これで一応映像部分は変換できるがQCELPが使用されているAMCファイルは音声が変換できない。
これはmencoder自体がAMCに直接対応しているわけではなく、AMCのビデオ部で使用されているMPEG4を自動検出してそのビデオの部分だけ変換しているらしい。
まぁビデオが変換できたことだけでも御の字かな。
Posted by tsujitako at 2:06 午前 in Linux/

木曜日, 24 2 月 2005

サプリメント依存症
この記事をクリップ!
このエントリーをはてなブックマークに追加

一人暮らししてるとどうしても晩飯が冷凍食品とかになってあまり栄養が摂れてない気がする、料理作る気なんか全然起こらんし、困った。
ということで結構前から栄養補給には気を遣ってサプリメントを摂り続けてるんだけれども、最近どうも摂り過ぎているような気が。
昔はもっと少なかったはずなんだけど、現在では10種類のサプリメントを摂るようになってしまった。
内訳はカルシウム、ビタミンC、ビタミンB群、マルチビタミン、食物繊維、DHA、レシチン、鉄、ベータカロチン、必須ミネラル。
これだけ飲んでるんだから十分栄養は摂ってるように思えるんだけど、もしかしたらまだ必要な栄養が足りていないかも。
そんなこと思ってると薬局行ったときにまた違うサプリメントを買ってしまいそう。
これってサプリメント依存症なのかね…これも困った。

現在飲んでるサプリメント。

「僕たちがご主人様の健康を守るからね!」お、お前たち、うぅ…。

Amazon
   
ネイチャーメイド
マルチビタミン&ミネラル 100粒
ネイチャーメイド
マルチビタミン ファミリーサイズ
ネイチャーメイド
C500
Posted by tsujitako at 2:34 午前 in 雑記/

水曜日, 23 2 月 2005

Cojenでバイトコード解析
この記事をクリップ!
このエントリーをはてなブックマークに追加

Javaで書かれたソースはコンパイルするとバイトコードと呼ばれるプラットホーム非依存の中間コードに変換される。
そのバイトコードを容易に解析、再構築するためのライブラリがCojenだ。
まずは解析するためのソースを用意する。今回用意したのは以下ような簡単なもの。
public class test{
  public static void main(String[] argv){
    test t=new test();
    t.print();
  }

  public test(){
  }

  public void print(){
    System.out.println("hello");
  }
}
これを普通にコンパイルする。
$ javac test.java
生成されたtest.classをCojenのディスアセンブラに通してみる。
$ java -cp cojen-1.1.0.jar:. cojen.classfile.DisassemblyTool test
すると以下のような出力が得られる。
/**
 * Disassembled on Wed Feb 23 01:53:47 JST 2005.
 * 
 * @target 1.2
 * @source test.java
 */
public class test extends java.lang.Object {
  public static void main(java.lang.String[]) {
    // max stack: 2
    // max locals: 1
    // line 5
    new test
    dup
    invokespecial void test.()
    astore_0
    // line 6
    aload_0
    invokevirtual void test.print()
    // line 7
    return
  }

  public void () {
    // max stack: 1
    // max locals: 1
    // line 10
    aload_0
    invokespecial void java.lang.Object.()
    // line 11
    return
  }

  public void print() {
    // max stack: 2
    // max locals: 1
    // line 15
    getstatic java.io.PrintStream java.lang.System.out
    ldc "hello"
    invokevirtual void java.io.PrintStream.println(java.lang.String)
    // line 16
    return
  }
}
上記の出力だけではjavapを使用して得られたバイトコードとほとんど変わらないが、以下の-f builderオプションを付けて実行するとクラスファイルを生成するためのJavaコードが得られる。
$ java -cp cojen-1.1.0.jar:. cojen.classfile.DisassemblyTool -f builder test
出力は以下の通り。
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

import cojen.classfile.ClassFile;
import cojen.classfile.CodeBuilder;
import cojen.classfile.FieldInfo;
import cojen.classfile.Label;
import cojen.classfile.LocalVariable;
import cojen.classfile.Location;
import cojen.classfile.MethodInfo;
import cojen.classfile.Modifiers;
import cojen.classfile.Opcode;
import cojen.classfile.TypeDesc;

/**
 * Builds ClassFile for test
 *
 * @author auto-generated
 */
public class ClassFileBuilder {
  public static void main(String[] args) throws Exception {
    // public class test
    ClassFile cf = createClassFile();

    if (args.length > 0) {
      File file = new File(args[0]);
      if (file.isDirectory()) {
        writeClassFiles(cf, file);
      } else {
        OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
        cf.writeTo(out);
        out.close();
      }
    }
  }

  private static void writeClassFiles(ClassFile cf, File dir) throws Exception {
    File file = new File(dir, cf.getClassName().replace('.', '/') + ".class");
    file.getParentFile().mkdirs();
    OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
    cf.writeTo(out);
    out.close();

    ClassFile[] innerClasses = cf.getInnerClasses();
    for (int i=0; i<innerClasses.length; i++) {
      writeClassFiles(innerClasses[i], dir);
    }
  }

  public static ClassFile createClassFile() {
    ClassFile cf = new ClassFile("test", "java.lang.Object");
    cf.setTarget("1.2");
    cf.setSourceFile("test.java");

    //
    // Create constructors
    //

    // public void <init>()
    createConstructor_1(cf);

    //
    // Create methods
    //

    // public static void main(java.lang.String[])
    createMethod_1(cf);

    // public void print()
    createMethod_2(cf);

    return cf;
  }

  // public void <init>()
  private static void createConstructor_1(ClassFile cf) {
    MethodInfo mi = cf.addConstructor(Modifiers.PUBLIC, null);
    CodeBuilder b = new CodeBuilder(mi);

    b.mapLineNumber(10);
    b.loadThis();
    b.invokeSuperConstructor(null);

    b.mapLineNumber(11);
    b.returnVoid();
  }

  // public static void main(java.lang.String[])
  private static void createMethod_1(ClassFile cf) {
    MethodInfo mi = cf.addMethod(Modifiers.PUBLIC_STATIC, "main", null, new TypeDesc[] {TypeDesc.STRING.toArrayType()});
    CodeBuilder b = new CodeBuilder(mi);

    LocalVariable var_1 = b.getParameter(0);

    b.mapLineNumber(5);
    TypeDesc type_1 = TypeDesc.forClass("test");
    b.newObject(type_1);
    b.dup();
    b.invokeConstructor(null);
    b.storeLocal(var_1);

    b.mapLineNumber(6);
    b.loadLocal(var_1);
    b.invokeVirtual("print", null, null);

    b.mapLineNumber(7);
    b.returnVoid();
  }

  // public void print()
  private static void createMethod_2(ClassFile cf) {
    MethodInfo mi = cf.addMethod(Modifiers.PUBLIC, "print", null, null);
    CodeBuilder b = new CodeBuilder(mi);

    b.mapLineNumber(15);
    TypeDesc type_1 = TypeDesc.forClass("java.io.PrintStream");
    b.loadStaticField("java.lang.System", "out", type_1);
    b.loadConstant("hello");
    TypeDesc[] params_1 = new TypeDesc[] {TypeDesc.STRING};
    b.invokeVirtual("java.io.PrintStream", "println", null, params_1);     b.mapLineNumber(16);     b.returnVoid();   } }
やたら長くて難解なコードだがよく見るとb.dup();のようなバイトコードのニーモニックそのままメソッドがあるためバイトコードの動きをそのままJavaで実装?しているようだ。
このコードをClassFileBuilder.javaという名前で保存し、コンパイルしてクラスファイルを生成してみる。
$ javac -classpath cojen-1.1.0.jar ClassFileBuilder.java
$ java -cp cojen-1.1.0.jar:. ClassFileBuilder test.class
するとtest.classが作成されるのでこれをjavaで実行する。
$ java -cp . test
hello
見事元のクラスファイルと同様の動きが再現された。
最近はAOPなどバイトコードレベルで処理を行う場合もあるためそういった低レベルな部分を解析、実装する場合は非常に役に立つのではないだろうか。
Posted by tsujitako at 2:19 午前 in Java/

火曜日, 22 2 月 2005

視力
この記事をクリップ!
このエントリーをはてなブックマークに追加

視力落ちてた…。右1.5、左1.0…。
(´・ω・`)ショボーン
Posted by tsujitako at 7:58 午後 in 雑記/

いざという時のBusyBox
この記事をクリップ!
このエントリーをはてなブックマークに追加

BusyBoxとは基本的なコマンド群を一つに納めたプログラムだ。lsやps、cpなど普段使うようなコマンド群がほぼ網羅されている。
平常時にこのBusyBoxを使う必要はないと思うが、いざという時に備えてこのコマンドを用意しておくべきだと思う。
仮に何かの拍子に共有ライブラリであるlibcが壊れたらlsすら出来なくなる。そういう時にスタティックリンクでコンパイルされたBusyBoxがあればとりあえず一通りの操作は可能になるだろう。
BusyBoxは一つのバイナリファイルなので各コマンドを実行するにはBusyBoxに実行したいコマンド名のシンボリックリンクを張るだけで完了だ。
$ make menuconfig (ここのBuild Optionsでstatic binaryを有効にすべき)
$ make dep
$ make
# make install
スタティックリンクを確認
$ ldd /bin/busybox
  not a dynamic executable
インストールが終わったら必要な分だけシンボリックリンクを張る。
# ln -s busybox ls
この状態でlsを実行するとbusybox内のlsが実行される。

備えあれば憂いなし、ということで。
Posted by tsujitako at 2:31 午前 in Linux/

月曜日, 21 2 月 2005

gjc VS jvm
この記事をクリップ!
このエントリーをはてなブックマークに追加

GNUのJavaコンパイラ、gcjがどれくらい速いのかちょっと試してみた。
以下のコードをサンプルとして使用。内容は50万個のオブジェクトを生成し、配列に順次入れていくというだけの簡単なもの。オブジェクトの生成コスト知りたかったので。
public class test{
  static final int SIZE=500000;

  public static void main(String[] args){
    long start=System.currentTimeMillis();

    testObj[] list=new testObj[SIZE];

    for(int i=0;i<SIZE;i++)
      list[i]=new testObj(i);

    long end=System.currentTimeMillis();

    System.out.println("takes "+(end-start)+" ms");
  }

  public static class testObj{
    private int _i;

    public testObj(int i){
      this._i=i;
    }
  }
}

実行環境: RH Linux 7.3(kernel 2.4.28)
Intel Celeron 1.70GHz 1GB Memory

・jvm (Sun J2SDK1.4.2_06)
$ javac test.java
$ java -cp . test
takes 313 ms

・gcj (3.3.2)
$ gcj --main=test test.java
$ gcj --main=test -o test test.java
$ ./test
takes 160 ms
これだけを見るとgcjでコンパイルしたネイティブコードの方が速いように見えるが、jvmの方はヒープの割り当てをデフォルトのままで実行しているのでこれをGCが発生しない量に設定し再度実行してみる。
$ java -Xms200m -Xmx200m -cp . test
takes 50 ms
GCさせななければjvmの方が圧倒的に速いようだ。
ただ現実的には余程簡単なプログラムでない限り無いGCの発生を無くすことはできないし、通常の込み入ったプログラムを使用した場合にも結果は変わってくるので比較結果はこの限りではないと思う。
Posted by tsujitako at 1:05 午前 in Java/

日曜日, 20 2 月 2005

Your Control: TunesでiTunes制御
この記事をクリップ!
このエントリーをはてなブックマークに追加

iTunesを外部から操作できるアプリケーションは数多くあるが、その中でもYour Control: Tunesは有用な機能が多く搭載されている。
メニューバーから直接iTune内にある曲の再生/停止/送り/戻しが可能で、再生している曲のアートワークや曲名を表示させる事も可能。
デスクトップに表示させずにメニューバーにティッカーとして曲名を表示させる事もできるので作業中でも意識を中断させることなく曲名を確認できるので便利だ。

再生停止も楽々。


今年もサマソニに出演して欲しいLostprophets。


AirMac Expressを買って風呂でも音楽を聴けるようにしたいと思う今日この頃。
Posted by tsujitako at 2:39 午前 in Mac/
前のページ   1 > 2 > 3   次のページ