关于class文件中常量池容量计数值的问题

巴海和 2013-08-09
Compiled from "VMTest.java"
public class vm.VMTest extends java.lang.Object
  SourceFile: "VMTest.java"
  minor version: 0
  major version: 50
  Constant pool:
const #1 = class	#2;	//  vm/VMTest
const #2 = Asciz	vm/VMTest;
const #3 = class	#4;	//  java/lang/Object
const #4 = Asciz	java/lang/Object;
const #5 = Asciz	<init>;
const #6 = Asciz	()V;
const #7 = Asciz	Code;
const #8 = Method	#3.#9;	//  java/lang/Object."<init>":()V
const #9 = NameAndType	#5:#6;//  "<init>":()V
const #10 = Asciz	LineNumberTable;
const #11 = Asciz	LocalVariableTable;
const #12 = Asciz	this;
const #13 = Asciz	Lvm/VMTest;;
const #14 = Asciz	main;
const #15 = Asciz	([Ljava/lang/String;)V;
const #16 = Asciz	Exceptions;
const #17 = class	#18;	//  java/lang/InterruptedException
const #18 = Asciz	java/lang/InterruptedException;
const #19 = long	10000l;
const #21 = Method	#22.#24;	//  java/lang/Thread.sleep:(J)V
const #22 = class	#23;	//  java/lang/Thread
const #23 = Asciz	java/lang/Thread;
const #24 = NameAndType	#25:#26;//  sleep:(J)V
const #25 = Asciz	sleep;
const #26 = Asciz	(J)V;
const #27 = class	#28;	//  vm/WaitThread
const #28 = Asciz	vm/WaitThread;
const #29 = Method	#27.#30;	//  vm/WaitThread."<init>":(I)V
const #30 = NameAndType	#5:#31;//  "<init>":(I)V
const #31 = Asciz	(I)V;
const #32 = Method	#22.#33;	//  java/lang/Thread."<init>":(Ljava/lang/Runnable;)V
const #33 = NameAndType	#5:#34;//  "<init>":(Ljava/lang/Runnable;)V
const #34 = Asciz	(Ljava/lang/Runnable;)V;
const #35 = Method	#22.#36;	//  java/lang/Thread.start:()V
const #36 = NameAndType	#37:#6;//  start:()V
const #37 = Asciz	start;
const #38 = Asciz	args;
const #39 = Asciz	[Ljava/lang/String;;
const #40 = Asciz	i;
const #41 = Asciz	I;
const #42 = Asciz	StackMapTable;
const #43 = Asciz	SourceFile;
const #44 = Asciz	VMTest.java;

{
public vm.VMTest();
  Code:
   Stack=1, Locals=1, Args_size=1
   0:	aload_0
   1:	invokespecial	#8; //Method java/lang/Object."<init>":()V
   4:	return
  LineNumberTable: 
   line 3: 0


public static void main(java.lang.String[])   throws java.lang.InterruptedException;
  Code:
   Stack=5, Locals=2, Args_size=1
   0:	iconst_0
   1:	istore_1
   2:	ldc2_w	#19; //long 10000l
   5:	invokestatic	#21; //Method java/lang/Thread.sleep:(J)V
   8:	new	#22; //class java/lang/Thread
   11:	dup
   12:	new	#27; //class vm/WaitThread
   15:	dup
   16:	iload_1
   17:	iinc	1, 1
   20:	invokespecial	#29; //Method vm/WaitThread."<init>":(I)V
   23:	invokespecial	#32; //Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V
   26:	invokevirtual	#35; //Method java/lang/Thread.start:()V
   29:	goto	2
  LineNumberTable: 
   line 6: 0
   line 8: 2
   line 9: 8
   line 7: 29

  StackMapTable: number_of_entries = 1
   frame_type = 252 /* append */
     offset_delta = 2
     locals = [ int ]

  Exceptions: 
   throws java.lang.InterruptedException
}

 为什么没有第20项常量呢?

 

Offset      0  1  2  3  4  5  6  7   8  9 10 11 12 13 14 15

00000000                            00 2D 07 00 02 01 00 09            -      
00000016   76 6D 2F 56 4D 54 65 73  74 07 00 04 01 00 10 6A   vm/VMTest      j
00000032   61 76 61 2F 6C 61 6E 67  2F 4F 62 6A 65 63 74 01   ava/lang/Object 
00000048   00 06 3C 69 6E 69 74 3E  01 00 03 28 29 56 01 00     <init>   ()V  
00000064   04 43 6F 64 65 0A 00 03  00 09 0C 00 05 00 06 01    Code           
00000080   00 0F 4C 69 6E 65 4E 75  6D 62 65 72 54 61 62 6C     LineNumberTabl
00000096   65 01 00 12 4C 6F 63 61  6C 56 61 72 69 61 62 6C   e   LocalVariabl
00000112   65 54 61 62 6C 65 01 00  04 74 68 69 73 01 00 0B   eTable   this   
00000128   4C 76 6D 2F 56 4D 54 65  73 74 3B 01 00 04 6D 61   Lvm/VMTest;   ma
00000144   69 6E 01 00 16 28 5B 4C  6A 61 76 61 2F 6C 61 6E   in   ([Ljava/lan
00000160   67 2F 53 74 72 69 6E 67  3B 29 56 01 00 0A 45 78   g/String;)V   Ex
00000176   63 65 70 74 69 6F 6E 73  07 00 12 01 00 1E 6A 61   ceptions      ja
00000192   76 61 2F 6C 61 6E 67 2F  49 6E 74 65 72 72 75 70   va/lang/Interrup
00000208   74 65 64 45 78 63 65 70  74 69 6F 6E 05 00 00 00   tedException    
00000224   00 00 00 27 10 0A 00 16  00 18 07 00 17 01 00 10      '            
00000240   6A 61 76 61 2F 6C 61 6E  67 2F 54 68 72 65 61 64   java/lang/Thread
00000256   0C 00 19 00 1A 01 00 05  73 6C 65 65 70 01 00 04           sleep   
00000272   28 4A 29 56 07 00 1C 01  00 0D 76 6D 2F 57 61 69   (J)V      vm/Wai
00000288   74 54 68 72 65 61 64 0A  00 1B 00 1E 0C 00 05 00   tThread         
00000304   1F 01 00 04 28 49 29 56  0A 00 16 00 21 0C 00 05       (I)V    !   
00000320   00 22 01 00 17 28 4C 6A  61 76 61 2F 6C 61 6E 67    "   (Ljava/lang
00000336   2F 52 75 6E 6E 61 62 6C  65 3B 29 56 0A 00 16 00   /Runnable;)V    
00000352   24 0C 00 25 00 06 01 00  05 73 74 61 72 74 01 00   $  %     start  
00000368   04 61 72 67 73 01 00 13  5B 4C 6A 61 76 61 2F 6C    args   [Ljava/l
00000384   61 6E 67 2F 53 74 72 69  6E 67 3B 01 00 01 69 01   ang/String;   i 
00000400   00 01 49 01 00 0D 53 74  61 63 6B 4D 61 70 54 61     I   StackMapTa
00000416   62 6C 65 01 00 0A 53 6F  75 72 63 65 46 69 6C 65   ble   SourceFile
00000432   01 00 0B 56 4D 54 65 73  74 2E 6A 61 76 61            VMTest.java

 

RednaxelaFX 2013-08-09
因为long和double都是占两个相邻constant pool entry的。HLLVM群组以前应该有过这个讨论。
巴海和 2013-08-09
RednaxelaFX 写道
因为long和double都是占两个相邻constant pool entry的。HLLVM群组以前应该有过这个讨论。

long和double相当于两个常量项?为什么呀?
RednaxelaFX 2013-08-10
巴海和 写道
RednaxelaFX 写道
因为long和double都是占两个相邻constant pool entry的。HLLVM群组以前应该有过这个讨论。

long和double相当于两个常量项?为什么呀?

您需要的是RTFM
Oracle blog上说RTFM是read the fine manual  

没啥,当初就是这么设计的(而且从后人的眼光看这个设计相当蛋疼

4.4.5. The CONSTANT_Long_info and CONSTANT_Double_info Structures
Java Virtual Machine Specification, Java SE 7 写道
All 8-byte constants take up two entries in the constant_pool table of the class file. If a CONSTANT_Long_info or CONSTANT_Double_info structure is the item in the constant_pool table at index n, then the next usable item in the pool is located at index n+2. The constant_pool index n+1 must be valid but is considered unusable.

In retrospect, making 8-byte constants take two constant pool entries was a poor choice.

规范里自带吐槽了。

当时是希望把Class文件设计成可以(尽量)直接(解释)执行,而且假定运行环境是32位(且要求数据32位对齐)的。这样long或double放不进一个32位的存储单元,就只能用两个相邻的32位存储单元来存了。于是常量池项、局部变量区、操作数栈等在JVM规范里都规定要用相邻的两个slot来存long或double类型的值。
Global site tag (gtag.js) - Google Analytics