- 浏览: 286230 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
chenchangqun:
这段示例代码没有客户端 没法实验
Java NIO原理和使用 -
congjl2002:
误,整理好了在发phk070832 写道垃圾代码,一大推的编译 ...
snmp trap的接收(jdmk方式) -
phk070832:
垃圾代码,一大推的编译错误,整理好了在发表吧。
snmp trap的接收(jdmk方式) -
zhangcctao:
我也遇到线程池的内存溢出问题。。不知道是不是这个原因呀?
多线程中使用静态方法 -
新入职:
分享了,这个eclise版本有没有讲究?我的3.3的可以么
windows下安装android及eclipse配置
从javaeye的论坛里看到这篇文章,感觉不错,转过来供自己学习
镜头1】 String对象的创建
1、关于类对象的创建,很普通的一种方式就是利用构造器,String类也不例外:
String s=new String("Hello world");
问题:参数"Hello world"是什么东西,也是字符串对象吗?莫非用字符串对象创建一个字符串对象???
2、当然,String类对象还有一种大家都很喜欢的创建方式:
String s="Hello world";
问题:有点怪呀,怎么与基本数据类型的赋值操作(int i=1)很像呀???
在开始解释这些问题之前,我们先引入一些必要的知识:
(1) Java class文件结构
我们都知道,Java程序要运行,首先需要编译器将源代码文件编译成字节码文件(也就是.class文件)。然后在由JVM解释执行。
class文件是8位字节的二进制流 。这些二进制流的涵义由一些紧凑的有意义的项 组成。比如class字节流中最开始的4个字节组成的项叫做魔数 (magic),其意义在于分辨class文件(值为0xCAFEBABE)与非class文件。class字节流大致结构如下图左侧。
其中,在class文件中有一个非常重要的项——常量池 。这个常量池专门放置源代码中的常量信息(并且不同的常量存放在不同标志的常量表中)。如上图右侧是HelloWorld代码中的常量表(HelloWorld代码如下),其中有四个不同类型的常量表(四个不同的常量池入口)。关于常量池的具体细节,请参照《深入Java虚拟机》第二版第6章。
public class HelloWorld{ void hello(){ System.out.println("Hello world"); } }
显然,HelloWorld代码中的"Hello world"被编译之后,可以清楚的看到存放在了class二进制流的常量池项中(上图右侧红框区域)。并且我们还发现常量池中专门有为String类型设置的常量表 。也就是说,在编译阶段,就已经将代码中的这种("****")形式作为了字符串常量存放在常量池中了 ,这一点和下面代码中出现的整形常量(142),浮点型常量(12.1)等的处理是没有区别的。
String s="Hello world";
int intData=142;
double dblData=12.1;
(2) Java虚拟机运行class文件
当Java虚拟机需要运行一个class文件时,它首先会用类装载器装载进class文件。当然也就需要在内存中存放许多东西。比如class的二进制字节码。还有需要存储class文件中得到的其他信息,比如程序创建的对象,传递给方法的参数,返回值,局部变量等等。怎么多麻烦的数据当然需要管理,JVM会把这些东西都组织到几个“运行时数据区 ”中。这些数据区中就有我们动不动就谈到的"堆"呀,"栈"呀什么的?想要详细了解这部分东西可以看《深入Java虚拟机》第二版第5章。
在这里我只谈谈“方法区 ”这个运行时数据区。在Java虚拟机中,关于被装载类型的信息会在一个逻辑上被称为"方法区"的内存中,当虚拟机装载某个类型时,它使用类装载器定位相应的class文件,然后读入该文件。紧接着虚拟机提取其中的类型信息,并将这些信息存储到方法区中。
方法区中的这些类型信息是很有用的,比如:这个类型的全限定名(net.single.HelloWorld);这个类型的直接超类的全限定名;这个类型是类类型还是接口类型;这个类型的访问修饰符(public,final,static)等。还有两个大家都很熟悉的引用:指向类ClassLoader的引用和指向Class类的引用。这是Java反射机制能够运行的关键所在。这里我们要提到的是一个非常重要的信息——该类型的常量池 。
上面提到的,class文件结构中的常量池二进制流就被JVM存储在方法区中进行管理。当程序运行时需要使用到常量值的时候,直接在方法区常量池所在的内存中寻找就可以了。
(3) 操作码助忆符指令集
将String s=new String("Hello world");编译成class文件后的指令(由eclipse打开class文件查看的):
- 0 new java.lang.String [15]
- 3 dup
- 4 ldc <String "Hello word"> [17]
- 6 invokespecial java.lang.String(java.lang.String) [19]
- 9 astore_1 [s]
- 10 retur
0 new java.lang.String [15] 3 dup 4 ldc <String "Hello word"> [17] 6 invokespecial java.lang.String(java.lang.String) [19] 9 astore_1 [s] 10 retur
下面通俗的解释一下这些指令,详细见《深入Java虚拟机》第二版附表:按操作码助忆符排列的指令集。
★ new指令: 在内存的堆区域中为新字符串对象分配足够大的空间,并将对象的实例变量设为默认值。
★ ldc指令:在内存的方法区常量池中找到String类型字面值常量表 的入口,然后定位到的"Hello word"所在内存中的位置。
★ invokespecial指令:调用指定的类构造器(这里调用的是String(String)这一个构造器。将ldc指令所找到的"Hello word"的内容传入到new指令所开辟在堆中的字符串对象中。
★ astore_1:将new指令所开辟堆的内存位置存入局部变量s中 。
将String s="Hello world";编译成class文件后的指令:
0 ldc <String "Hello world"> [15] 2 astore_1 [str] 3 return
★ ldc指令:在内存的方法区常量池中找到String类型字面值常量表 的入口,然后定位到的"Hello word"所在内存中的位置(如果常量池中没有"Hello word",则会在其中添加一个"Hello word")。
★ astore_1:将ldc指令定位到的常量池中的位置存入局部变量s中 。
镜头总结: String类型脱光了其实也很普通。真正让她神秘的原因就在于String类型字面值常量表 的存在。
相关问题解决
(问题1) 代码1 代码2
String sa=new String("Hello world"); String sc="Hello world";
String sb=new String("Hello world"); String sd="Hello world";
System.out.println(sa==sb); // false System.out.println(sc==sd); // true
变量sa,sb中存储的内容是JVM在堆中开辟的两个String对象的内存地址。==比较就是sa,sb变量存储的内容,也就是两个不同的内存地址,当然是false;
变量sc,sd中存储的内容也是地址,但却都是方法区常量池中"Hello word"所在的地址,自然一样。
(问题2) 代码1 代码2
String sa = "ab"; String sc="ab"+"cd";
String sb = "cd"; String sd="abcd";
String sab=sa+sb; System.out.println(sc==sd); //true
String s="abcd";
System.out.println(sab==s); // false
代码1中sa+sb被编译以后使用的是StringBuilder.append(String)方法。JVM会在堆中创建一个StringBuilder类,将sa所指向常量池中的内容"ab"传入,然后调用append(sb所指向的常量池内容)完成字符串合并功能,最后将堆中StringBuilder对象的地址赋给变量sab。而s存储的是常量池中"abcd"的地址。sab与s地址当然不一样了。
代码2中"ab"+"cd"会直接在编译阶段就合并成常量"abcd",所以相同的字符串在常量池中的地址也相同了。
发表评论
-
java阻塞队列学习(转帖)
2010-06-06 11:50 3441import java.util.concurrent.Arr ... -
httpclient链接关闭问题(转帖)
2010-03-11 22:09 2071HttpClient client = new HttpCli ... -
J2EE集群原理(转贴)
2010-03-09 19:57 1173J2EE集群原理 什么是集群呢?总的来说,集群包括两个概念: ... -
Spring 实现ibatis事务回滚
2010-03-05 20:34 3581网上发现这篇文章,转过来学习一下,好不好用还没有实践,需要自己 ... -
java 可变参数
2009-12-14 20:50 14057vararg的意思是变量参数,它是与Jav ... -
使用JDBC对BLOB和CLOB进行处理
2009-11-12 20:33 4811从网上看到这篇文章,转过来做为学习用 设有表:create ... -
避免或最小化 Servlet 中的同步
2009-09-24 21:02 942servlet 是多线程的。基于 servlet 的应用程序必 ... -
httpclient 使用小记
2009-09-03 21:05 3352最近学习apache的httpclient 在使用postm ... -
httpclient 学习笔记
2009-08-23 16:52 1489前阵子,学习了一下APACHE 的httpclient,感觉h ... -
log4j使用
2009-06-19 21:08 1516从网上看到得,发现写 ... -
java虚拟机的一些概念
2009-05-24 10:22 1302从网上看到这篇文章,感觉适合初学jvm,就转来作为以后学习参考 ... -
xmlbean 生成带包路径的jar
2009-05-23 23:12 3247因为使用xmlbean生成 ... -
多线程中使用静态方法
2009-05-14 19:54 6587终于把内存泄漏问题解决了,不是多线程访问静态函数的问题,事实证 ... -
java Annotation入门
2009-04-16 21:22 1204因为偶然的原因需要使用Annotation,所以从网上找了这篇 ... -
MINA2.0简单使用
2009-04-12 16:12 5087一直知道MINA是apache 开发的一个开发socket编程 ... -
log4j参数配置说明
2009-03-22 20:31 1973前几天用到log4j,到网上查了一下他的参数配置,发现还是比较 ... -
portal之SSO开发文档
2009-03-02 20:12 3984前两天看到别人写的,感觉不错,就转了过来做为参考 ... -
cas在tomcat中的配置
2009-02-25 21:22 2769cas在tomcat上配置时,需要打开tomc ... -
SSO 原理浅谈
2009-02-25 19:41 2076SSO 是一个非常大的主题,我对这个主题有着深深的感受,自从 ... -
ajax iframe 无刷新上传文件
2009-02-04 09:53 8627首先要说的就是 ajax 是无法实现上传文件的,可以想 ...
相关推荐
java中String类型转换方法.pdf
简单总结可以下Java中String类中的常用方法
83.java中String构造方法.zip83.java中String构造方法.zip83.java中String构造方法.zip83.java中String构造方法.zip83.java中String构造方法.zip83.java中String构造方法.zip83.java中String构造方法.zip83.java中...
85.java中String构造方法.zip85.java中String构造方法.zip85.java中String构造方法.zip85.java中String构造方法.zip85.java中String构造方法.zip85.java中String构造方法.zip85.java中String构造方法.zip85.java中...
86.java中String对象的特点.zip86.java中String对象的特点.zip86.java中String对象的特点.zip86.java中String对象的特点.zip86.java中String对象的特点.zip86.java中String对象的特点.zip86.java中String对象的特点....
JAVA中String与StringBuffer的区别 JAVA中String与StringBuffer的区别 自己的学习笔记总结
介绍java中String类的方法,String类实例的创造
主要介绍了Java中String判断值为null或空及地址是否相等的问题,文中举了简单的例子对字符串类型的值和地址问题进行讲解,需要的朋友可以参考下
Java中String类和常用方法 实例化String对象
小心String的陷阱——深入剖析Java中String的处理机制
java中String_十六进制String_byte[]之间相互转换
自己整理的Java中String类的详细文档打印版
java中string和int型的相互转换.doc
Java中String的知识点
Java中string和ArrayList的API
java中String和StringBuffer有何不同,从物理存储方式上剖析
java中String的常用方法
java基础String类选择题练习题,文档包含了答案与分析,适合学习用,本文档仅仅用于学习分享,不得用于商业用途
Java中String类.pdf 学习资料 复习资料 教学资源
java中String类型和int类型比较及相互转换