そういえば、少し前、私のブログに40個弱のスパムコメントがつきました。
いや、私のブログになんかコメントつけてスパムとして何か意味あるのか?、という話は置いておくとして、「どこかで見たような文章だなー」とか思ったりしたのですが、よくよく見てみると全部元のブログエントリか、他のコメントからの文章引き写しでだったりしました。で、その中に
さかもとです。
とか見つけると、「これ、そもそもの引用元もスパムだったんじゃないかー」とか思ったりしますw
やまだです。
いやー、こー暑いとプールにでも行きたいですねー。
ということで、今回は Java クラスファイルのコンスタントプールのお話です。
コンスタントプールとは、もう名の通り、コンスタントのプールです。もうコンスタントが芋洗い状態でわらわらとw
悪い言い方をすると、文字列とかその他の情報を「ええい面倒だ、全部まとめて一緒に入れちまえっ!」ってな感じですね。
まず、サンプルコードで、全く中身のないプログラムを書いてみます。
public class Main1 {
int i = 62584;
double d = 15.42;
String s = "yamada";
public static void main(String[] args) {
}
}
で、これから生成されたクラスファイルのコンスタントプールを覗いてみると、以下のようになってたりします。
コンスタントプールの各エントリはTLV(Tag-Length-Value)形式(*1)で構成されています。つまり、可変長データなわけです。
*1 冒頭の Tag でデータの種類、次にデータの長さ、そのあとにデータの中身を格納する、という可変長データを表現するときの汎用形式
とりあえず、まずはひとつひとつの中身にはこだわらないことにして、これ、何かおかしいとは思いませんでしょうか?
コンスタントプール数が32なのに、1から数えてみたら31までしか含まれていないんですよね。でも、それがJava VMの仕様なんです。
コンスタントプールには、「コンスタントプール数」で定義された個数-1しかエントリがない仕様だったりすると。
……いや、それ普通、仕様バグって言わない?
で、もっとちゃんと見てみると、実際には、さらに一つ足りないんです。上記だと、5番が抜けています。
これって、このツールのバグ……ではなくて、これもJava VM の仕様だったりすると。
long や double の変数の定義では、それぞれ2エントリ分を使用する、という仕様になっているようです。
……ちょっと待て。そもそも、コンスタントプールの各エントリって固定長ならいざ知らず、可変長ですよ?エントリを2つ潰す意味あるの?
……いや、それ普通、仕様バグって言わない?
まぁ、そうやらざるをえない諸般の事情はあったんでしょう、下位互換性を保たないといけないという考え方もあるでしょう。
でも、前回のエントリで書いたバージョン識別のメカニズムがあるんだから、バージョンを判断して過去のバージョンだったときだけ下位互換性を保てば良いのではないの、とか思ったりします。
つーか、そんな変な仕様をずっと引きずるなよー、とか思うのは私だけでしょうか?
で、Java のソースコードと ConstantPool の対比の話を全く何も書いていないので、それは次の機会があれば、ということで。
では。