`

j2se----String

    博客分类:
  • J2SE
阅读更多
  "a" == "a"
  new String("a") == new String("a")
 new String("a") == "a"
1.true
2.false
3.false
使用new String("a")时,jvm是不会主动把该对象放到strings pool里面的,除非程序调用 String的intern方法。比如: String a = new String("a"); a.intern();
注意:new String("a");
"a" 是一个参数,被传给String构造器,所以jvm先到运行时常量池中去找"a", 如果找到了,那么拷贝一个"a"放到堆上,如果没有找到,先生成一个放到常量池中,然后在拷贝一份放到堆上。 如果使用了s.intern(); 那么他会把堆上的那个对象和常量池中的对象匹配,如果找到了则返回常量池中的那个对象,如果没找到现把堆上的那个对象移动到池中,然后再返回。(注意 有可能常量池中的对象在某个时候消失了也有可能)

runtime data area

1. 程序计数器
2. Java 虚拟机栈
3. 本地方法栈( Native Method Stacks )
4. Java 堆( Java Heap )
5. 方法区( Method Area )
6. 运行时常量池( Runtime Constant Pool )
7.本机直接内存( Direct Memory )

String s = new String("xyz");创建了几个String Object? 二者之间有什么区别?
两个或一个,”xyz”对应一个对象,这个对象放在字符串常量缓冲区,常量”xyz”不管出现多少遍,都是缓冲区中的那一个。New String每写一遍,就创建一个新的对象,它一句那个常量”xyz”对象的内容来创建出一个新String对象。如果以前就用过’xyz’,这句代表就不会创建”xyz”自己了,直接从缓冲区拿。

1.String s1 = "a";   
2.String s2 = s1.concat("");   
3.String s3 = null;   
4.new String(s1);  
以及3个String实例, 
1、"a"字面量对应的驻留的字符串常量的String实例 
2、""字面量对应的驻留的字符串常量的String实例 
(String.concat()是个有趣的方法,当发现传入的参数是空字符串时会返回this,所以这里不会额外创建新的String实例) 
3、通过new String(String)创建的新String实例;没有任何变量指向它。
------------------------------------------------------------------
String实现了equals方法,new String(“abc”).equals(new String(“abc”)的结果为true,
StringBuffer没有实现equals方法,所以,new StringBuffer(“abc”).equals(new StringBuffer(“abc”)的结果为false。

-------------------------------------------------------------------------
如果一个字符串变量是在方法里面定义,这种情况只可能有一个线程访问它,不存在不安全的因素了,则用StringBuilder。如果要在类里面定义成员变量,并且这个类的实例对象会在多线程环境下使用,那么最好用StringBuffer。

String s1 = "a";
String s2 = s1 + "b";
String s3 = "a" + "b";
System.out.println(s2 == "ab");
System.out.println(s3 == "ab");
第一条语句打印的结果为false,第二条语句打印的结果为true,这说明javac编译可以对字符串常量直接相加的表达式进行优化,不必要等到运行期去进行加法运算处理,而是在编译时去掉其中的加号,直接将其编译成一个这些常量相连的结果。常量相加优化结果为直接拼成一个对象,而变量相加优化结果是使用StringBuilder
题目中的第一行代码被编译器在编译时优化后,相当于直接定义了一个”abcd”的字符串,所以,上面的代码应该只创建了一个String对象。写如下两行代码,
		String s = "a" + "b" + "c" + "d";
		System.out.println(s == "abcd");
最终打印的结果应该为true。 
但是要区别于下面的东西:
String str = "";
for(int i=0;i<1000;i++){  //这个循环会产生1000次的哈
   str +="3";
}


下面是runtime data area 详解,抄过来的
1. 程序计数器( Program Counter Register ): 

  

每一个 Java 线程都有一个程序计数器来用于保存程序执行到当前方法的哪一个指令,对于非 Native 方法,这个区域记录的是正在执行的 VM 原语的地址,如果正在执行的是 Natvie 方法,这个区域则为空( undefined )。此内存区域是唯一一个在 VM Spec 中没有规定任何 OutOfMemoryError 情况的区域。 

  

2. Java 虚拟机栈( Java Virtual Machine Stacks ) 

与程序计数器一样, VM 栈的生命周期也是与线程相同。 VM 栈描述的是 Java 方法调用的内存模型:每个方法被执行的时候,都会同时创建一个帧( Frame )用于存储本地变量表、操作栈、动态链接、方法出入口等信息。每一个方法的调用至完成,就意味着一个帧在 VM 栈中的入栈至出栈的过程。在后文中,我们将着重讨论 VM 栈中本地变量表部分。 

经常有人把 Java 内存简单的区分为堆内存( Heap )和栈内存( Stack ),实际中的区域远比这种观点复杂,这样划分只是说明与变量定义密切相关的内存区域是这两块。其中所指的“堆”后面会专门描述,而所指的“栈”就是 VM 栈中各个帧的本地变量表部分。本地变量表存放了编译期可知的各种标量类型( boolean 、 byte 、 char 、 short 、 int 、 float 、 long 、 double )、对象引用(不是对象本身,仅仅是一个引用指针)、方法返回地址等。其中 long 和 double 会占用 2 个本地变量空间( 32bit ),其余占用 1 个。本地变量表在进入方法时进行分配,当进入一个方法时,这个方法需要在帧中分配多大的本地变量是一件完全确定的事情,在方法运行期间不改变本地变量表的大小。 

在 VM Spec 中对这个区域规定了 2 中异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出 StackOverflowError 异常;如果 VM 栈可以动态扩展( VM Spec 中允许固定长度的 VM 栈),当扩展时无法申请到足够内存则抛出 OutOfMemoryError 异常。 



3. 本地方法栈( Native Method Stacks ) 

本地方法栈与 VM 栈所发挥作用是类似的,只不过 VM 栈为虚拟机运行 VM 原语服务,而本地方法栈是为虚拟机使用到的 Native 方法服务。它的实现的语言、方式与结构并没有强制规定,甚至有的虚拟机(譬如 Sun Hotspot 虚拟机)直接就把本地方法栈和 VM 栈合二为一。和 VM 栈一样,这个区域也会抛出 StackOverflowError 和 OutOfMemoryError 异常。 


4.Java 堆( Java Heap ) 

对于绝大多数应用来说, Java 堆是虚拟机管理最大的一块内存。 Java 堆是被所有线程共享的,在虚拟机启动时创建。 Java 堆的唯一目的就是存放对象实例,绝大部分的对象实例都在这里分配。这一点在 VM Spec 中的描述是:所有的实例以及数组都在堆上分配(原文: The heap is the runtime data area from which memory for all class instances and arrays is allocated ),但是在逃逸分析和标量替换优化技术出现后, VM Spec 的描述就显得并不那么准确了。 

Java 堆内还有更细致的划分:新生代、老年代,再细致一点的: eden 、 from survivor 、 to survivor ,甚至更细粒度的本地线程分配缓冲( TLAB )等,无论对 Java 堆如何划分,目的都是为了更好的回收内存,或者更快的分配内存,在本章中我们仅仅针对内存区域的作用进行讨论, Java 堆中的上述各个区域的细节,可参见本文第二章《 JVM 内存管理:深入垃圾收集器与内存分配策略》。 

根据 VM Spec 的要求, Java 堆可以处于物理上不连续的内存空间,它逻辑上是连续的即可,就像我们的磁盘空间一样。实现时可以选择实现成固定大小的,也可以是可扩展的,不过当前所有商业的虚拟机都是按照可扩展来实现的(通过 -Xmx 和 -Xms 控制)。如果在堆中无法分配内存,并且堆也无法再扩展时,将会抛出 OutOfMemoryError 异常。 



5. 方法区( Method Area ) 

叫“方法区”可能认识它的人还不太多,如果叫永久代( Permanent Generation )它的粉丝也许就多了。它还有个别名叫做 Non-Heap (非堆),但是 VM Spec 上则描述方法区为堆的一个逻辑部分(原文: the method area is logically part of the heap ),这个名字的问题还真容易令人产生误解,我们在这里就不纠结了。 

方法区中存放了每个 Class 的结构信息,包括常量池、字段描述、方法描述等等。 VM Space 描述中对这个区域的限制非常宽松,除了和 Java 堆一样不需要连续的内存,也可以选择固定大小或者可扩展外,甚至可以选择不实现垃圾收集。相对来说,垃圾收集行为在这个区域是相对比较少发生的,但并不是某些描述那样永久代不会发生 GC (至少对当前主流的商业 JVM 实现来说是如此),这里的 GC 主要是对常量池的回收和对类的卸载,虽然回收的“成绩”一般也比较差强人意,尤其是类卸载,条件相当苛刻。 



6. 运行时常量池( Runtime Constant Pool ) 

Class 文件中除了有类的版本、字段、方法、接口等描述等信息外,还有一项信息是常量表 (constant_pool table) ,用于存放编译期已可知的常量,这部分内容将在类加载后进入方法区(永久代)存放。但是 Java 语言并不要求常量一定只有编译期预置入 Class 的常量表的内容才能进入方法区常量池,运行期间也可将新内容放入常量池(最典型的 String.intern() 方法)。 

运行时常量池是方法区的一部分,自然受到方法区内存的限制,当常量池无法在申请到内存时会抛出 OutOfMemoryError 异常。 

  

7. 本机直接内存( Direct Memory ) 

直接内存并不是虚拟机运行时数据区的一部分,它根本就是本机内存而不是 VM 直接管理的区域。但是这部分内存也会导致 OutOfMemoryError 异常出现,因此我们放到这里一起描述。 

在 JDK1.4 中新加入了 NIO 类,引入一种基于渠道与缓冲区的 I/O 方式,它可以通过本机 Native 函数库直接分配本机内存,然后通过一个存储在 Java 堆里面的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在 Java 对和本机堆中来回复制数据。 

显然本机直接内存的分配不会受到 Java 堆大小的限制,但是即然是内存那肯定还是要受到本机物理内存(包括 SWAP 区或者 Windows 虚拟内存)的限制的,一般服务器管理员配置 JVM 参数时,会根据实际内存设置 -Xmx 等参数信息,但经常忽略掉直接内存,使得各个内存区域总和大于物理内存限制(包括物理的和操作系统级的限制),而导致动态扩展时出现 OutOfMemoryError 异常。 



分享到:
评论

相关推荐

    j2se-doc-cn java的API文档,有助于你写JAVA程序

    Java API文档是学习和开发Java程序的重要资源,它包含了Java平台标准版(J2SE)的所有公共类、接口和方法的详细说明。这份名为“j2se-doc-cn”的压缩包包含的是Java API的中文版,对于中国开发者来说,无疑极大地...

    j2se-server.rar_connect

    String inputLine; StringBuilder content = new StringBuilder(); while ((inputLine = in.readLine()) != null) { content.append(inputLine); } in.close(); connection.disconnect(); ``` 对于POST请求,你还...

    java面试题大全(j2se->jsp->ssh->oracle)

    - `String s = new String("xyz");` 创建了两个字符串对象:一个是常量池中的 "xyz",另一个是通过 `new` 关键字创建的对象。 ### 8. Math 类的 round 方法 - `Math.round(11.5)` 返回 12。 - `Math.round(-11.5)`...

    j2se1.5中文api

    《J2SE1.5中文API详解》 Java 2 Platform, Standard Edition (J2SE) 1.5,也被称为Java SE 5.0,是Java编程语言的一个重要版本,它引入了大量的新特性和改进,对Java开发者来说具有里程碑式的意义。J2SE 1.5中文API...

    java-j2se.rar_j2se

    4. **字符串处理**:String类的特性,如不可变性、常用方法(substring、indexOf、concat等)以及StringBuilder和StringBuffer的使用。 5. **异常处理**:Java中的异常分类(检查异常与非检查异常)、try-catch-...

    J2SE面试题总汇

    - **String 类**:不可变的字符串,常用方法如 equals()、substring()、concat() 等。 - **StringBuilder 和 StringBuffer**:可变字符串,适合在循环中进行字符串操作。 十二、流: - **I/O 流**:用于读写数据,...

    J2SE复习源代码

    Java 2 Standard Edition(J2SE)是Java平台的核心部分,用于开发和运行桌面应用程序、服务器端应用以及嵌入式系统。本复习源代码涵盖了多个关键知识点,旨在帮助开发者巩固和提升在J2SE中的技能。 1. **常用类**:...

    学好j2se的标准

    这涉及多个包,如`java.lang`中的基础类(如String、Object、Math),`java.util`中的集合框架、正则表达式、日期时间处理,`java.io`中的输入/输出流,`java.math`中的大数运算,`java.net`中的网络通信,`java....

    j2se中文6.0api

    1. **Java基础类库**:包括核心类如`Object`、`String`、`Arrays`等,以及集合框架如`List`、`Set`、`Map`。这些类库为日常编程提供了基本的数据结构和操作方法。 2. **异常处理**:Java的异常处理机制通过`try-...

    J2SE中表格应用

    根据提供的文件信息,本文将详细解析“J2SE中表格应用”的相关知识点,重点在于如何在Java Swing中使用`JTable`组件,并结合代码示例进行深入分析。 ### J2SE与Swing简介 Java 2 Standard Edition (J2SE) 是Java...

    j2se7官方API

    Java 2 Standard Edition 7(简称J2SE 7或Java 7)是Java平台的一个重要版本,它引入了一系列新特性和改进,旨在提高开发人员的效率和代码的可维护性。官方API文档是理解这些特性和接口的关键资源。下面我们将深入...

    J2EE与J2SE路径获取

    ### J2EE与J2SE路径获取方法详解 在Java开发过程中,无论是针对J2EE还是J2SE项目,路径的获取都是非常基础且重要的环节。本文将详细介绍在J2EE和J2SE环境下如何获取不同类型的路径,并通过具体示例进行说明。 ####...

    J2SE 核心类库源代码

    Java 2 Platform, Standard Edition (J2SE) 是 Java 平台的核心部分,它提供了用于开发和运行桌面应用、服务器应用以及嵌入式系统的环境。J2SE 的核心类库包含了丰富的 API,这些 API 覆盖了从基本数据类型到网络...

    Java-J2SE学习笔记

    6. **字符串**:Java中的String类是不可变的,理解它的特性,以及如何进行字符串拼接、查找、替换等操作。 接下来,笔记可能会涉及面向对象编程的概念: 7. **类与对象**:理解类作为数据结构和行为的蓝图,以及...

    面向后台,j2se部分都是基础,主要学习: 面向对-Java-Summary-of-Basic-Learning.zip

    - String类:不可变性,字符串连接,查找子串,替换子串等操作。 - StringBuilder和StringBuffer:可变字符串,用于大量字符串拼接操作。 5. **输入/输出流**: - 文件操作:File类,文件的创建、读写、删除。 ...

    j2SE中文API帮助文档

    `java.lang`是最基础的包,包含了所有Java程序都会用到的基本类型和对象,如`String`、`Object`和异常处理类。`java.util`提供了集合框架、日期时间、随机数生成等功能。`java.io`包用于输入/输出操作,包括文件读写...

    J2SE 学习心得(一些常用知识要点)PART1

    Java Standard Edition (J2SE) 是 Java 语言的核心部分,提供了构建桌面应用和网络服务的基础。在学习 J2SE 的过程中,了解并掌握其基础知识至关重要。以下是一些关键知识点: 1. 参数传递:在 Java 中,基本数据...

    J2SE.rar_J2SE在线查询_j2se chm

    9. **泛型**:自J2SE 5.0起引入的泛型增强了类型安全性,如`List&lt;String&gt;`,CHM文件会详细解析泛型的概念和用法。 10. **枚举类型**:J2SE 5.0新增的枚举类型是固定数量常量的集合,CHM文件会介绍如何定义和使用...

    J2SE API中文版

    例如`java.lang`包中的`Object`类是所有类的父类,`String`类用于处理文本数据,`Math`类提供数学函数。 2. **集合框架**:Java集合框架是处理对象集合的重要工具,包括接口如`List`、`Set`、`Map`和实现类如`...

Global site tag (gtag.js) - Google Analytics