在Java中,Java的设计者对String对象进行了大量的优化,主要有三个特点

1.不变性:

不变性是指String对象一旦生成,则不能再对它进行改变。String的这个特点可以泛化成不变(immutable)模式,一个对象的状态在对象被创建之后就不再发生变化。不变模式的主要作用在于,当一个对象需要被多线程共享,并且访问频繁时,可以省略同步和锁等待的时间,从而大幅提升系统性能。

不变性可以提高多线程访问的性能。因为对象不可变,因此对于所有线程都是只读的,多线程访问时,即使不加同步也不会产生数据的不一致,故减少了系统的开销。

由于不变性,一些看起来像是修改的操作,实际上都是依靠产生新的字符串实现的。比如 String.substring(),String.concat()方法,他们都没有修改原始字符串,而是产生了一个新的字符串。

如果需要一个可以修改的字符串,那么需要使用StringBuffer或者StringBuilder对象。

2.针对常量池的优化

针对常量池的优化指当两个String对象拥有相同的值时,他们只引用常量池中的同一个拷贝。当同一个字符串反复出现时,这个技术可以大幅节省内存空间。

        String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(str1==str2);//false
System.out.println(str1==str2.intern());//false
System.out.println("abc"==str2.intern());//true
System.out.println(str1.intern()==str2.intern());//true

以上代码str1和str2都开辟了一块堆空间存放String实例。虽然str1和str2内容相同,但是在堆空间中的引用是不同的。String.intern()返回字符串在常量池中的引用,显然它和str1也是不相同的,String.intern()始终和常量字符串相等。

3.类的final定义

final类型定义也是String对象的重要特点。作为final类的String对象在系统中不可能有任何子类,这是对系统安全性的保护。

有关String的内存泄漏

内存泄漏就是程序未能释放已经不再使用的内存的情况,他并不是说物理内存消失了,而是指由于不再使用的对象占据内存不被释放,而导致可用内存不断减小,最终有可能导致内存溢出。

以String.substring()方法为例,说明内存泄漏问题:

java.lang.String主要由3部分组成:代表字符数组的value、偏移量offset和长度count.这个结构为内存泄漏埋下伏笔,字符串的实际内容有value,offset,count三者共同决定,而非value一项。如果字符串value数组包含100个字符,而count长度只有1个字节,那么这个String实际上只要1个字符,却占据了至少100个字节,那剩余的99个就属于泄漏的部分,他们不会被使用,不会被释放,却长期占用内存,直到字符串本身被回收。

这种情况在JDK1.6中非常容易出现。String.substring()中,新生成的String并没有从value中获取自己需要的那部分,而是简单的使用了相同的value引用,只是修改了offset和count,以此类确定新的String对象的值。当原始字符串没有被回收时,这种情况是没有问题的,并且通过共用value,还可以节省一部分内存,但是一旦原始字符串被回收,value中多余的部分就造成了空间浪费。

综上所述,如果使用了String.substing()将一个大字符串切割为小字符串,当大字符串被回收时,小字符串的存在就会引起内存泄漏。

在JDK1.7中,去掉了offset和count两项,而String的实质性内容仅由value决定,而value数组本身就代表了这个String实际的取值。

Java虚拟机九 java.lang.String在虚拟机中的实现的更多相关文章

  1. java学习(九) —— java中的File文件操作及IO流概述

    前言 流是干什么的:为了永久性的保存数据. IO流用来处理设备之间的数据传输(上传和下载文件) java对数据的操作是通过流的方式. java用于操作流的对象都在IO包中. java IO系统的学习, ...

  2. 《深入理解Java虚拟机》Java内存区域与内存溢出异常

    注:“蓝色加粗字体”为书本原语 先来一张JVM运行时数据区域图,再接下来一一分析各区域功能:   程序计数器 程序计数器(program Counter Register)是一块较小的内存空间,它可以 ...

  3. JDK1.8源码(三)——java.lang.String 类

    String 类也是java.lang 包下的一个类,算是日常编码中最常用的一个类了,那么本篇博客就来详细的介绍 String 类. 1.String 类的定义 public final class ...

  4. JAVA虚拟机体系结构JAVA虚拟机的生命周期

    一个运行时的Java虚拟机实例的天职是:负责运行一个java程序.当启动一个Java程序时,一个虚拟机实例也就诞生了.当该程序关闭退出,这个虚拟机实例也就随之消亡.如果同一台计算机上同时运行三个Jav ...

  5. JDK源码-java.lang.String

    1.开篇明志 本文来看看String的源码. 2.Java7 API String介绍 String 类代表字符串.Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现. 字符串 ...

  6. 《深入理解Java虚拟机》- Java虚拟机是如何加载Java类的?

    Java虚拟机是如何加载Java类的?  这个问题也就是面试常问到的Java类加载机制.在年初面试百战之后,菜鸟喜鹊也是能把这流程倒背如流啊!但是,也只是字面上的背诵,根本就是像上学时背书考试一样. ...

  7. Java虚拟机栈(java stack)

    虚拟机栈(java stack) 百度图片搜索里的动图搜索功能不错,可以搜索一些动图,展示操作数栈的操作过程,比较形象.这点google差点意思 虚拟机栈(jvm stacks)是线程独占的 里面是多 ...

  8. 【Java】实战Java虚拟机之五“开启JIT编译”

    今天开始实战Java虚拟机之五“开启JIT编译” 总计有5个系列 实战Java虚拟机之一“堆溢出处理” 实战Java虚拟机之二“虚拟机的工作模式” 实战Java虚拟机之三“G1的新生代GC” 实战Ja ...

  9. 深入理解java虚拟机【Java内存结构】

    Java虚拟机规范规定的java虚拟机内存其实就是java虚拟机运行时数据区,其架构如下: 其中方法区和堆是由所有线程共享的数据区. Java虚拟机栈,本地方法栈和程序计数器是线程隔离的数据区. (1 ...

随机推荐

  1. 双向认证SSL原理

    http://m.blog.chinaunix.net/uid-540802-id-3170984.html 文中首先解释了加密解密的一些基础知识和概念,然后通过一个加密通信过程的例子说明了加密算法的 ...

  2. 从debian9、ubuntu18.04的deb包依赖来看,似乎不是那么好!!

    i386体系的依赖.典型的libuuid1依赖问题,需要downgrade保持版本一致! amd64的rpm依赖低版本的perl-base,需要downgrade保持版本一致!

  3. Unity3D热更新LuaFramework入门实战

    http://blog.sina.com.cn/s/blog_6788cd880102w8qy.html http://www.manew.com/thread-91845-1-1.html http ...

  4. 怎么让BarTender对象等间距分布

    在BarTender 2016设计条码标签时,我们需要让对象分布尽可能整齐美观,例如实现对象的对齐,对象等间距分布等.这些在作为世界上最好且最受信任的条码打印软件BarTender中,都是可以很轻松的 ...

  5. spring boot整合activemq消息中间件

    spring boot整合activemq消息中间件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi ...

  6. [OpenCV] Samples 15: Background Subtraction and Gaussian mixture models

    不错的草稿.但进一步处理是必然的,也是难点所在. Extended: 固定摄像头,采用Gaussian mixture models对背景建模. OpenCV 中实现了两个版本的高斯混合背景/前景分割 ...

  7. 为什么调用 FragmentPagerAdapter.notifyDataSetChanged() 并不能更新其 Fragment?【转载】

    转载自:http://www.cnblogs.com/dancefire/archive/2013/01/02/why-notifyDataSetChanged-does-not-work.html ...

  8. passport登录问题:passport.use 方法没有被调用

    写passport登录验证时,无论如何passport.use 方法都没有被调用,最后在同事的帮助下,才找到问题: 我是用form提交登陆数据的, input type:"text" ...

  9. The import XXX cannot be resolved

    选择project --> clean后,OK.如果还不行,删掉全部import,然后按alt+/提示,逐个导入.

  10. hadoop的Map阶段的四大步骤

    深入理解map的几个阶段是怎样执行的.