インスタンスをprintするとなぜ文字列が出てくるの!

今日も色々と得ることがありました。

復習でハッとしたこともありましたけど、もちろん新しく学んだことも。

忘れないうちに今日も書いておこう。

到達不能コード(と、条件コンパイル)とSystem.out.println(obj)の話。

まずは到達不能コードについて。

[java]
public class Main {
	public static void main(String[] args){
		while(false){
			System.out.println("ここにはたどり着けない");
		}
	}

}
[/java]

こういうのが到達不能コード。

詳細はJava言語の仕様14.20にある。

このサイトとかいいかも。

http://www.y-adagio.com/public/standards/tr_javalang2/statements.doc.html

これによるとif(DEBUG){ x = 3;}はコンパイルエラーにならないそうな。

実際ならないし、これはassertを使うときに便利みたい。

というのも結城さんのJava言語で学ぶリファクタリング入門を読んでて、そこに載ってたから知ったってだけなんですけどね。

assert文を条件コンパイルすればクラスファイルが小さくなるらしい。

System.out.println(obj)の話。

これもリファクタリング学習中にあれ?と思ったことなんですけど。

事の発端は以下のコードから。

[java]
public class Sample {
	public String toString(){
		return "Sampleクラスです";
	}
}
[/java]
[java]
public class Main {
	public static void main(String[] args) {
		Sample sample = new Sample();
		System.out.println("sampleを引数に取ると : " + sample);
	}
}
[/java]

これを実行すると結果はsampleを引数に取ると : Sampleクラスです

となる。

なぜこうなる・・・と15分くらい悩みましたけど、そう・・・printlnを見てみればいいんですよね。

ctrlを押しながらprintlnをクリックして宣言もとへジャンプ。

eclipseは便利ですな。

[java]
    public void println(Object obj)
    {
        String s = String.valueOf(obj);
        synchronized(this)
        {
            print(s);
            newLine();
        }
    }
[/java]

ふむ、なるほどvalueOfを呼んでるわけだ。

[java]
    public static String valueOf(Object obj)
    {
        return obj != null ? obj.toString() : "null";
    }
[/java]

なるほど、ここでtoStringを呼んでいる。だからか・・・!

toStringのオーバーライド前の挙動も見てみましたけど、それは説明だるいので省略。

C言語で同じように実装見てみようと思うと凄くだるそう。そもそも普通に理解できるように書かれているのだろうか。

後確かprintfとかってバイナリになってるから別にソースを用意しておく必要がありそうな・・。

まあ今度やってみよう。

追記(2010/08/03)

友人に間違いを指摘されたので追記。

println(obj)は中でtoStringやっててってのはあってるわけだけど、

System.out.println(“sampleを引数に取ると : ” + sample);

これはpublic void println(String s)が呼び出される。

けど+演算で結局は同じobj=>String変換が行われる。

というわけで半分あってました。

mallocが余分に確保する理由(未解決)

本日のテーマはmalloc

このmallocを使ったときにメモリが余分に確保される訳だけど、それはなぜ?って話。

結論から言うと未解決です。クソ記事です。

なので検索してきた方はごめんなさい。

でもまあまったく無駄という訳でもなかったのでとりあえず書くだけ書いてみる。

本題に入る前に予備知識とか。

まずCで型や変数のサイズを調べたい時はsizeofを使うけど、mallocで確保したサイズを知りたい時にsizeofは使えない。

正しくは以下のようにmalloc.hをインクルードしてmalloc_usable_sizeを使う。

[c]
#include <stdio.h>
#include <malloc.h>
int main(void){
  char s1[] = "12345";
  char *s2;
  printf("sizeof(s1)=%d\n", sizeof(s1));
  s2 = malloc(sizeof(s1));

  //mallocで確保した分を見たい場合は正しくはこう
  printf("malloc_usable_size(s2)=%d\n", malloc_usable_size(s2));
  return 0;
}
[/c]

次にアラインメントの話。

これは書くと長くなるので他に任せる。

ようするに高速化とかのために多少空白ができてしまっても決められた境界に値を置くようにするということ。

ここから本題。

じゃあ上記のプログラムを実行したらメモリはいくつ確保される訳!

自分の予想ではそのままの値、

つまりsizeof(s1)が\0を入れて6文字なので6バイト確保される。

またはアラインメントを意識して8バイトとかなのではないかと。

所が64bit環境で実行したところ、24という結果に。

かなり意味不明。確かに2の倍数ではある。8の倍数でもある。

けど多く取りすぎじゃない・・・!?

今度はs1を”0123456789012345678901234″、\0を入れて25文字にして実行したところ今度は40

どうやら24,40,56と増えていく模様。

いや16ずつ増えるのはわかったよ。多分アラインメントは16バイトなんだろう。

けど初めの24って何よ!8バイト余計なのは何なの!

ちなみに32bit環境で実行すると12,20,28,36と増える模様。

半分になってる。

気になったのでこういうのに詳しい後輩にアドバイス貰ったり、色々調べました。

結果として得られたことは以下の通り。

  • 64bit環境で16Byteずつ、32bitで8Byteずつ増えるのは最も長いlong doubleを意識しているため。
  • メモリにはChunkという機構があるけど、このChunkをmallocしたときにn個使う(確保する)
  • だから16or8Byteずつ増えていく。
  • (未解決)64bit環境で初めに24Byte確保する。16ByteはChunkだとして残りの余計な8ByteはChunkの管理情報

という具合。

結局2日くらいかけて調べたけれど完全解決に至らなくて悔しい。

その余計な8Byte(32bitだと4Byte)は本当に管理情報なのだろうか・・・。

この問題はまた暇なときかメモリ回りで困ったときに調べることにしよう。

以下、参考情報。

VA Linuxのmalloc解説。ここ結構凄いかもです。

http://www.valinux.co.jp/contents/tech/techlib/eos/malloc/malloc_001.html

追記(2010/06/28)

俺の友人の中で1,2を争う天才に助け舟を出してみて以下のことが分かったのでmemo。

  • そもそもmalloc_usable_sizeは標準関数じゃない。
  • 調べてもいまいち分からないし、malloc_usable_sizeが返す値は怪しい。
  • mallocの実装によるけどK&R本なんかの例では線形リストっぽい管理の仕方をしている。

ああ、いまいち有益な情報になってない。・・・というか検索してもあんまり的確な情報が出てこないってのはどうでもいいことなのかもしれない。

・・・または単に俺の検索能力が低いだけか。

動的束縛(dynamic binding)

自分は物凄く忘れっぽい。

なので今日から技術的なことも恥ずかしがらずにどんどん書いていこう。

僅かではあるけれど情報発信にもなるし無益ということはないだろうし。

(情報の正確さには気を付けないといけないけど・・・)

今日のお題はdynamic binding, dynamic dispatching

動的束縛とか動的結合とも言われるみたい。

・・・というか調べても全然日本語サイトがヒットしなくて涙目。

現状ではdynamic binding = dynamic dispatching = 動的結合 = 動的束縛 という認識。

で、内容はというと

「どういう物だっけ?」

「どのメソッドが実行されるかは実行時でないと分からない、ってなんだっけ?」

という話。ポリモーフィズムの話。

ちなみに以下のサイトも参考になるので、俺のとこより良いかもしれません。

http://d.hatena.ne.jp/m383m/20080129/1201611382

ちょっと違うけどキャスト回りについて詳しい

http://www.kab-studio.biz/Programing/OOPinJava/08/03.html

まず例として以下のコードがあるとする。

[java]
public class Super {

    public void printMyClassName(){
        System.out.println("Super");
    }

}
[/java]

Superクラスを継承してメソッドをオーバーライドしている。

[java]
public class Sub extends Super {

    public void printMyClassName(){
        System.out.println("Sub");
    }

}
[/java]

上記のクラスを使用するためのMainクラス。

[java]
public class Main {

    public static void main(String[] args) {
    Super s;
    s = new Sub();

    s.printMyClassName();
    }

}
[/java]

Super sという参照型変数があるが中身はnew Sub() つまり、型としてはSuperだが実体はSub

なのでmainメソッドは”Sub”を出力する。

今日の本題はここから・・・!

上記のそれを動的束縛だとか言うけど、正直どこら辺が動的なの?

普通にコンパイル前でもどのメソッドが実行されるかわかるじゃん。なんなんだよ!と。

忘れているうえにろくに考えない俺に、友人がなんとも的確なコードを示してくれました!

[java]
public class Main {

    public static void main(String[] args) {
    Super s;

    if(args.length == 0)
        s = new Sub();
    else
        s = new Super();

    s.printMyClassName();
    }

}
[/java]

なるほど・・・!これなら実行時までどっちのメソッドか分からない!

そうかこれが動的結合!これがポリモーフィズムだったんだ!

ちなみに一応解説するとs = new Super()は変数も実体もSuperなので当然、オーバーライド前のメソッドが実行されます。(”Super”と出力される)

流石にこれだけ書けば忘れないだろう。

ようやく終了

6月14日にようやく就職活動終了しました。

社員数2000-3000名の中堅~大企業です。

もっとも子会社なので大手ではないですけど。

メーカー系SIerなので福利厚生だとか給与は悪くなさそうです。

良いともいえないようですけど。

とにかく無事、終わってよかったです。

一時はどうなることかと思いましたけど、続けていれば決まるものですね。

採用してくれたこの会社のためにも、俺のためにも誠心誠意、勤めを果たしたいと思います。

具体的には

資格面で30までにIPAのAP,NW,DB、OracleMaster Silver取得。

職種の面では35までにPMとして成長。

技術面では40までにDBとコード保守で社内1。

を目指したい思います。

APは現状で午前650、午後500くらいの力はあるのでたぶん入社前に2か月勉強すれば取れる。

しかし大学院修了後で24なので6年間でNW,DB,OracleMaster Silverを取るとなると・・・どうなんだろうか。

DB系はまあ良いとしてもNWがやる気の面でも、現状の知識量の面でも、覚えることの多さの面でもゲンナリ。こいつは苦労しそう。

35でPMはまあありえるかもしれない。

けど40で社内一の技術者ってのはどうなることやら。

というのもどうやら俺の内々定先は職種としてスペシャリストが用意されているみたいだから。

つまりPM路線に行ったとしたら、まあ普通に考えてDBのスペシャリストにはかなわないっていう。

色々曖昧な点もありますけど、ソフトウェア開発プロセスとDBを武器にしていきたいです。

さあ、気持ちを切り替えて研究頑張ろう。

「うちでは”開発”やってないんですけど」

今日も就職活動。

面接と説明会で1日潰れました。

午前中の面接は微妙な出来でした。

特に納得行かなかった点が1つあったので今日はその話。

初めに自己PRをして、その話の流れで過去に~~~や~~~の開発を行いましたって言ったわけですよ。

でもって志望動機は勿論「開発がしたい」と言ったわけではなく、~~~に貢献したいって言いました。

そして最後の最後に面接官が一言

「あおかびさんはよく開発という言葉を使ってらっしゃいますが、当社では開発はやってないんですよ。パートナーさんに頼むので。その点はご理解頂いていますでしょうか?」

いや、まあただの確認だろうし大したことじゃないですけど。

話の流れから俺の言ってる開発=コーディングだけ、じゃないことは分かるでしょう。

上手くとはいかずともちゃんと要件定義も設計もテストも行いましたよ。

それら一連のソフトウェア、システム作りを”開発”と言っちゃまずいんでしょうか・・・。

コンサル会社に「うちは開発やってないんですよ」って言われりゃ納得するけど、御社の場合思いっきり営業、提案、設計、果ては工事までやってるじゃないですか。

うーむ、納得いかねえ。

次からは気をつけよう。

就職活動状況の話。

これだけやって決まらないと自分は社会にとって不要なのではないかと思えてくる。

しかし最終面接まで行ける様にはなってきたので、諦めてはいけない。

最終結果待ち:1

最終面接待ち:2

1次面接結果待ち:1

まだだ・・・まだ頑張れる!