随笔-57  评论-129  文章-0  trackbacks-0
最近看见一个JavaEye上关于Java基本类型编译优化的帖子。
貌似高深莫测,其实疑点重重。吧内容转贴过来,希望在这里找到更合理的解释。
引用网上看得一些文章

 int a = 3;
 int b = 3;

  编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处 理int b = 3;在创建完b的引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。这样,就出现了a与b同时均指向3的情况。

再令a=4;那么,b不会等于4,还是等于3。在编译器内部,遇到a=4;时,它就会重新搜索栈中是否有4的字面值,如果没有,重新开辟地址存放4的值;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值

不知道真正的原理是不是那样的?

如果是的话能证明吗?

这些描述我也看过,很是不解。

如果说这种基本类型也需要用这种指针的风格,还要共享数据,那么后续的操作处理起来不是更麻烦吗?
每次写操作都要查找已有常量。甚至开辟新的空间存储新值。
再说这个指针怎么的也要个32位吧。为什么就不能直接吧值放进去,硬是要通过指针跳来跳去的,有意义吗?
这优化了吗?

反正在我看来,这是不可能的。

希望有高手出来澄清一下,给个合理的解释。

如果是对的,那也应该给出有点说服力的证据。
如果是错的,那么建议大家吧这篇文章的源头揪出来,这个确实误人不浅。

不过java对 String 这类不可变对象的处理,编译器确实有类似优化,不过也只是编译期。
这种系统类库受到点编译器的特别关注倒是很合理的。



posted on 2007-07-30 08:29 金大为 阅读(1158) 评论(12)  编辑  收藏 所属分类: Java

评论:
# re: 一片可能是误认子弟的言论 2007-07-30 09:16 | Unmi
我怎么没见过说对
int a=3;
int b=b;
编译器会作如此的优化呢?从两次产生的字节码是不会的

int a=3;
int b=3;

String s1="hello";
String s2="hello";

产生的字节码
0: iconst_3 //整型常量值3压栈
1: istore_1 //从栈中弹出整型值,存到位置为1的局部变量中
2: iconst_3 //整型常量值3压栈
3: istore_2 //从栈中弹出整型值,存到位置为2的局部变量中
4: ldc #2; //String hello //2号位置的字符串常量压栈
6: astore_3 //从栈中弹出字符串值,存到位置为3的局部变量中
7: ldc #2; //String hello //2号位置的字符串常量压栈
9: astore 4 //从栈中弹出字符串值,存到位置为4的局部变量中

希望从上面的字节码能让你理解字符串常量
我就是不知道你是在哪里看到那篇文章的。  回复  更多评论
  
# re: 一片可能是误认子弟的言论 2007-07-30 09:31 | wangzx
确实是被人误了。对int这样的JVM基本类型,根本不存在指针和共享的概念。  回复  更多评论
  
# re: 一片可能是误认子弟的言论 2007-07-30 09:38 | 金大为
我还是在4年前刚开始学Java时看到的,因为对里面的内容实在不敢苟同,感觉就像是那位吃饱了撑着没事干的大牛吧人家愚人节的blog给翻译过来了。印象比较深刻。但是,原文在那里,我已经不记得了。总之是一片广泛流传的东西。

这次我是在javaEye的帖子里看到的:http://www.javaeye.com/topic/102430  回复  更多评论
  
# re: 一篇可能是误认子弟的言论 2007-07-30 10:18 | Sun
有些人学了一点东西就自认高手
什么都敢说
一点不负责任  回复  更多评论
  
# re: 一篇可能是误认子弟的言论 2007-07-30 10:53 | dennis
我真没看过这篇文章,不知道在那里有出处,我倒想去看看,这个问题其实看过深入java虚拟机就没什么疑问了。  回复  更多评论
  
# re: 一篇可能是误认子弟的言论 2007-07-30 11:06 | pass86
学习。  回复  更多评论
  
# re: 一篇可能是误认子弟的言论 2007-07-30 11:06 | dennis
可以肯定是基本类型是没有什么内存共享和指针的,效率考虑上也不需要。不同的地方在于基本类型变量定义在何处,在类的变量或者方法的局部变量是有一点小差异,类的实例变量和类变量在常量池中有入口,不过他们入口就是他们的值,而不是类似接口、类的符号引用,同样需要常量池解析这个步骤(直接解析)。而对于静态的final变量都是在编译时解析为常量值的本地拷贝。
public class Test
{
int a=3;
int b=3;
static int c=3;
public void test(){
int a=3;
int b=3;
int c=this.c;
}

}

javap -v Test  回复  更多评论
  
# re: 一篇可能是误认子弟的言论[未登录] 2007-07-30 11:31 | dd
的确是有一个常量池的
public class dd
{
public static void main(String ... args)
{
Integer a=-1; //-1到127
Integer b=-1;
System.out.println(a==b);
String str1="dd";
String str2="dd";
System.out.println(str1==str2);
}
}
没有new 出一个对象,值都是存进常量池里的。


  回复  更多评论
  
# re: 一篇可能是误认子弟的言论 2007-07-30 11:51 | dennis
@dd
你的理解错了,你的例子中main仅仅是一个方法,里面的变量都是局部变量,这些变量都以指令的形式写在了字节码中,当调用方法是,这些变量也仅仅在java栈的局部变量区内,而不是常量池,方法调用也就是入栈出栈的操作。而常量池用于存储类的名称、方法和字段名称以及串常量等信息,这是完全不同的。  回复  更多评论
  
# re: 一篇可能是误认子弟的言论 2007-07-30 14:09 | 金大为
@dd
我把你这段程序的字节码贴出来

// access flags 137
public static transient varargs main([Ljava/lang/String;)V
L0 (0)
LINENUMBER 6 L0
ICONST_M1
INVOKESTATIC java/lang/Integer.valueOf(I)Ljava/lang/Integer;
ASTORE 1
L1 (4)
LINENUMBER 7 L1
ICONST_M1
INVOKESTATIC java/lang/Integer.valueOf(I)Ljava/lang/Integer;
ASTORE 2
L2 (8)
LINENUMBER 8 L2
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ALOAD 1
ALOAD 2
IF_ACMPNE L3
ICONST_1
GOTO L4
L3 (15)
ICONST_0
L4 (17)
INVOKEVIRTUAL java/io/PrintStream.println(Z)V
L5 (19)
LINENUMBER 10 L5
LDC "dd"
ASTORE 3
L6 (22)
LINENUMBER 11 L6
LDC "dd"
ASTORE 4
L7 (25)
LINENUMBER 12 L7
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ALOAD 3
ALOAD 4
IF_ACMPNE L8
ICONST_1
GOTO L9
L8 (32)
ICONST_0
L9 (34)
INVOKEVIRTUAL java/io/PrintStream.println(Z)V
L10 (36)
LINENUMBER 13 L10
RETURN
L11 (38)
LOCALVARIABLE args [Ljava/lang/String; L0 L11 0
LOCALVARIABLE a Ljava/lang/Integer; L1 L11 1
LOCALVARIABLE b Ljava/lang/Integer; L2 L11 2
LOCALVARIABLE str1 Ljava/lang/String; L6 L11 3
LOCALVARIABLE str2 Ljava/lang/String; L7 L11 4
MAXSTACK = 3
MAXLOCALS = 5  回复  更多评论
  
# re: 一篇可能是误认子弟的言论 2007-07-30 14:17 | 金大为
对于Integer对象的直接原始类型(int)赋值,将编译成Integer.valueOf(原始int值)。
两个Integer对象之所以地址相等,完全是Java5类库层面的缓存所至。
与上面讨论的常量池无关。
这个一看Integer.valueOf实现就明白了。  回复  更多评论
  
# re: 一篇可能是误认子弟的言论 2007-07-31 14:51 | BruceLuo
我想起来了,这是台湾良格GE写的吧,我没有记错的话,他原来的是写的是int a =100;int b =100吧。。。。希望大家帮忙找下!  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: