Fork me on GitHub

2011/03/06


このエントリーをはてなブックマークに追加
public class foo {
    final static String bar = "a" + "b";

    public foo() { }

    public String bar(String baz) {
        return "a" + "b" + baz + "c" + "d";
    }
}
コンパイルしてデコンパイル
# javac -version
javac 1.6.0_24
# javac foo.java
# jad foo.class
// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/kpdus/jad.html
// Decompiler options: packimports(3) 
// Source File Name:   foo.java


public class foo
{

    public foo()
    {
    }

    public String bar(String s)
    {
        return (new StringBuilder()).append("ab").append(s).append("c").append("d").toString();
    }

    static final String bar = "ab";
}
+ をStringBuilder に置き換えてくれたまでは良かった。a と b は最適化されて一つの ab になったけど c と d はそのままだ。
この最適化が有効なのは、業務のソースなんかでたまに見かける
String sql = "SELECT "
           + "  * "
           + " FROM "
           + "  USER_MST"
           + " WHERE "
           + "  BAR = ?";

PreparedStatement stmt = con.prepareStatement(sql);
stmt.setString(1"baz");
こんなソースの場合だと思うんだけど、テーブル名なんかを変数に持ってて
String sql = "SELECT "
    + " * "
    + " FROM "
    + " " + tableName
    + " WHERE "
    + "     BAR = ?";
こんな事しちゃうと、変数以降の最適化が StringBuilder での最適化に止まってしまう。まぁよく見るよね。こういうコード。
String s1 = (new StringBuilder()).append("SELECT *  FROM ").append(s).append(" WHERE ").append(" BAR = ?").toString();
PreparedStatement preparedstatement = connection.prepareStatement(s1);
preparedstatement.setString(1, "baz");
しばらく「最近のJavaはconstなStringを結合して最適化する」っていうのはやめておこうと思った。
Posted at 01:24 in ソフトウェア::lang::java
Tagged as: java
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip

2009/10/08


このエントリーをはてなブックマークに追加
Javaで...
class test{public static void main(String[]a){for(int n=1;n<101;n++)System.out.println(n%15>0?n%3>0?n%5>0?""+n:"Buzz":"Fizz":"FizzBuzz");}}
むー139バイトで46位。遠いなー。

じゃぁRubyで...
puts (1..100).map{|i|i%15==0%1?:FizzBuzz:i%3==0?:Fizz:i%5==0?:Buzz:i}
むむー。72バイトで65位。遠いよー。

なっ...ならばLuaで!!!汗...
for v=1,100 do print(v%15>0 and(v%3>0 and(v%5>0 and v or"Buzz")or"Fizz")or"FizzBuzz")end
88バイトで11位。ムキーーーーッ!

寝る!
Posted at 02:01 in ソフトウェア::lang::java
Tagged as: golf, java, lua, programming, ruby
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip

2009/04/08


このエントリーをはてなブックマークに追加
きたー!
Google App Engine Blog: Seriously this time, the new language on App Engine: Java™

Today, we're very excited to announce the availability of a new programming language for Google App Engine. Please welcome the Java runtime!

http://googleappengine.blogspot.com/2009/04/seriously-this-time-new-language-on-app.html
で、最初はEarly Lockというサーバを更新出来ない状態だったけど何故かさっき「Lock解除したよ」のメールが来た。

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
    <body>
        Hello JSP!<br />
    </body>
</html>

ここで動いてます。

ちなみに、上の記事によるとGAEでCronが動かせる様になった。こっちの方が嬉しい人いるんじゃないかな?
Posted at 15:05 in web
Tagged as: google, google app engine, java
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip

2008/07/23


このエントリーをはてなブックマークに追加
遅ればせながらGoogle Protocol Buffersで遊んでみました。
protobuf - Google Code
Protocol Buffers are a way of encoding structured data in an efficient yet extensible format. Google uses Protocol Buffers for almost all of its internal RPC protocols and file formats.
まず、インストールは以下の様に行いました。なおprotobufを展開したフォルダは以下のフォルダ。
C:¥temp¥protobuf-2.0.0beta¥

cpp版のインストール

展開したフォルダのvsprojectsフォルダにある"protobuf.sln"をVisual Studioで開きReleaseビルド。
必要であれば環境変数PATHの通る場所へ"protoc.exe"、"libprotobuf.dll"、"libprotoc.dll"を置く。また"libprotobuf.lib"と"libprotoc.lib"はコンパイル時に必要になるので分かりやすい位置に置いておく。

java版のインストール

まずApache MavenをインストールしPATHを通す。
次にjavaフォルダへ移動し
C:¥temp¥protobuf-2.0.0beta¥java> mvn test install
とすれば必要なライブラリがダウンロードされ、テスト後インストールされる。
targetフォルダに"protobuf-java-2.0.0beta.jar"が出来るのでこれまた分かりやすい位置に置く。

python版のインストール

pythonフォルダに移動し、cpp版をビルドした際に出来上がった"protoc.exe"にパスが通っている事を確認して
C:¥temp¥protobuf-2.0.0beta¥python> python setup.py bdist_wininst
...
C:¥temp¥protobuf-2.0.0beta¥python> cd dist
C:¥temp¥protobuf-2.0.0beta¥python¥dist> protobuf-2.0.0beta.win32.exe
※Windowsじゃない人は"bdist_wininst"の代わりに"bdist_rpm"とか"install"とか...

テストコードによる検証

まずデータ定義となるprotoファイルを作る。詳しい説明は省略するが知りたい人はココとかココとか。今回は名前と年齢を格納出来るPersonクラスを扱う。
person.proto
package protocol;

message Person {
  required string name = 1;
  required int32  age  = 2;
}

このファイルを指定して、スタブクラスを生成する。
まずcpp版。
C:¥temp¥protobuf-2.0.0beta¥tmp> protoc --cpp_out=. person.proto
これで"person.pb.cc"と"person.pb.h"が生成される。以下テストコード。
test.cpp
#include <iostream>
#include <fstream>
#include <person.pb.h>

void save(const char* fn) {
    protocol::Person person;

    person.set_name("mattn");
    person.set_age(18);

    std::ofstream ofs(fn);
    person.SerializeToOstream(&ofs);
    ofs.close();
}

void load(const char* fn) {
    protocol::Person person;

    std::ifstream ifs(fn);
    person.ParseFromIstream(&ifs);

    std::cout <<
        "name:" << person.name() <<
        ",age:" << person.age() << std::endl;
}

int main(int argc, char* argv[]) {
    if (argc != 2) return -1;

    save(argv[1]);
    load(argv[1]);

    return 0;
}
ビルドは以下の手順で行う。
C:¥temp¥protobuf-2.0.0beta¥tmp> cl -I../src -I. /EHsc test.cpp person.pb.cc libprotoc.lib libprotobuf.lib
実行すると
C:¥temp¥protobuf-2.0.0beta¥tmp> test person_cpp.txt
name:mattn,age:18
と表示される。そう...18歳です。ウソです。
生成される"person_cpp.txt"は以下の様なファイルとなる。

^Emattn^P#
次にjava版。"person.proto"というファイル名からPersonクラスを生成する際にファイル名がバッティングしてしまうので"persons.proto"という別名にコピーしておく。
C:¥temp¥protobuf-2.0.0beta¥tmp> protoc --java_out=. persons.proto
"protocol/Persons.java"が生成される。
テストコードは以下の通り。
test.java
import protocol.Persons;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class test {
    public static void main(String[] args) throws Exception {
        Persons.Person.Builder personBuilder = Persons.Person.newBuilder();
        Persons.Person mattn = personBuilder.setName("mattn").setAge(18).build();

        FileOutputStream fos = new FileOutputStream(args[0]);
        mattn.writeTo(fos);
        fos.close();

        FileInputStream fin = new FileInputStream(args[0]);
        mattn = Persons.Person.parseFrom(fin);
        fin.close();

        System.out.printf("name:%s,age:%d", mattn.getName(), mattn.getAge());
    }
}
ビルドは以下の手順で行う。
C:¥temp¥protobuf-2.0.0beta¥tmp> javac -classpath protobuf-java-2.0.0beta.jar; test.java
実行結果はcpp版と同様。

最後にpython版。
C:¥temp¥protobuf-2.0.0beta¥tmp> protoc --python_out=. person.proto
"person_pb2.py"が生成される。以下テストコード
test.py
import sys
from person_pb2 import Person

fn = sys.argv[1]

person = Person()
person.name = "mattn"
person.age = 18
open(fn, "w").write(person.SerializeToString())

person = Person()
person.ParseFromString(open(fn).read())
print "name:%s,age:%d" % (person.name, person.age)
実行結果はcpp版、java版と同様。

所感

結局の所、"protocol buffers"とは、"Serialize Format"生成ツールおよびライブラリと、"Serializable"なクラス郡と言った所だろうか。
実際にはRPC等で転送してみないと良さは分からないかもしれないけど、XMLの様に自信がValidation可能な物ではなさそうなので転送の際には外側からデータのサイズ送信やチェックサム実施も必要になるかもしれない。
そういった意味では、「【ハウツー】XMLはもう不要!? Google製シリアライズツール「Protocol Buffer」 (2) ダウンロードとインストール | エンタープライズ | マイコミジャーナル」の"XMLはもう不要!?"には少し疑問を感じる。

時間があれば、ネットワーク上にシリアライズしたデータを転送してみたいと思う。
Posted at 20:46 in ソフトウェア
Tagged as: cpp, google, java, protocol buffer, python
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip