关于 String.intern() 的思考】的更多相关文章

详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt399 我看到一个问题 https://segmentfault.com/q/10... 是关于 String.intern() 的, 感觉比较有意思, 于是自己也去探索了一下, 有了一些自己的见解, 于是在此记录下来. 我们首先来看一个例子: // 1 String str1 = new StringBuilder("ja").append("va&qu…
https://www.jianshu.com/p/af6eb8d3d4bf 首先看一段程序: using System; class Program { static void Main(string[] args) { string a = "hello world"; string b = a; a = "hello"; Console.WriteLine("{0}, {1}", a, b); Console.WriteLine(a ==…
1. 首先String不属于8种基本数据类型,String是一个对象.   因为对象的默认值是null,所以String的默认值也是null:但它又是一种特殊的对象,有其它对象没有的一些特性. 2. new String()和new String(“”)都是申明一个新的空字符串,是空串不是null: 3. String str=”kvill”:  String str=new String (“kvill”);的区别: 在这里,我们不谈堆,也不谈栈,只先简单引入常量池这个简单的概念.  常量池(…
原文出处: codelog.me 大家知道,Java中string.intern()方法调用会先去字符串常量池中查找相应的字符串,如果字符串不存在,就会在字符串常量池中创建该字符串然后再返回. 字符串常量池是一个固定大小的HashMap,桶的数量默认是1009, 从Java7u40开始,该默认值增大到60013.在Java6当中,字符串常量池是放在Perm空间的,从Java7开始,字符串常量池被移到Heap空间.下面,我们通过测试程序来窥探字符串常量池在Java6,Java7两个不同版本底下的内…
JDK7将String常量池从Perm区移动到了Java Heap区.在JDK1.6中,intern方法会把首次遇到的字符串实例复制到永久代中,返回的也是永久代中的实例.但是在JDK1.7以后,String.intern()方法不会在复制实例,只是在常量池中记录首次出现的实例引用.下面来看一些具体例子. 案例一: String str1 = new String("计算机") + new String("软件"); System.out.println(str1.i…
运行时常量池概述 Java运行时常量池中主要存放两大类常量:字面量和符号引用.字面量比较接近于Java语言层面的常量概念,如文本字符串.声明为final的常量值等. 而符号引用则属于编译原理方面的概念,包括了下面三类常量: - 类和接口的全限定名(包名+类名) - 字段的名称和描述符 - 方法的名称和描述符 运行时常量池位置 运行时常量池在JDK1.6及之前版本的JVM中是方法区的一部分,而在HotSpot虚拟机中方法区放在了"永久代(Permanent Generation)".所以…
字符串常量池也是运行时常量池 jdk1.6中,它是在方法区中,属于“永久代” jdk1.7中,它被移除方法区,放在java堆中 jdk1.8中,取消了“永久代”,将常量池放在元空间,与堆独立了 public class RuntimeConstantPoolOOM { public static void main(String[] args) throws Exception{ String str1 = new StringBuffer("计算机").append("sh…
在翻<深入理解Java虚拟机>的书时,又看到了2-7的 String.intern()返回引用的测试. 总结一句话: jdk1.7之前,调用intern()方法会判断常量池是否有该字符串,有,返回常量池引用,没有,常量池中创建并返回引用给intern方法. jdk1.7之后,调用intern()方法会判断常量池是否有该字符串,有,返回常量池引用,没有,常量池中保存当前对象的引用. 其实要搞明白String.intern(),我总结了下面几条规则: 一.jdk1.7之前,new String都是…
运行时常量池,之前放在方法区(永久代)中,1.8之后被转移到元空间,放到了native memory中. 具体的数据结构是:(看对象的内存布局,句柄访问还是对象头中保存指向类的元数据的指针,这里以对象头markword之后保存指向元数据指针为例)对象有一个指向类元数据的指针,指向的这个数据结构InstanceClass, InstanceKlass有一个指针指向一个constantPool数据结构(运行时常量池),这个数据结构是一个数组,数组里面元素的排列方式和class文件中是一样的(从1号常…
在jdk7下慎用String.intern()作为synchronized的对象锁: https://www.cnblogs.com/yhlx/p/3498387.html String.intern()在jdk7的变化后,我们为了在单例类里并发时对同一个用户保证操作原子性,会加同步块,例如: synchronized (("" + userId).intern()) { // TODO:something } 这个在jdk6里问题不算大,因为String.intern()会在perm…
一个初始为空的字符串池,它由类 String 私有地维护. 当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串.否则,将此 String 对象添加到池中,并返回此 String 对象的引用. 它遵循以下规则:对于任意两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true. 所有字面值字符串和字符串赋值常量表达式都使…
引言 在 JAVA 语言中有8中基本类型和一种比较特殊的类型String.这些类型为了使他们在运行过程中速度更快,更节省内存,都提供了一种常量池的概念.常量池就类似一个JAVA系统级别提供的缓存. 8种基本类型的常量池都是系统协调的,String类型的常量池比较特殊.它的主要使用方法有两种: 直接使用双引号声明出来的String对象会直接存储在常量池中. 如果不是用双引号声明的String对象,可以使用String提供的intern方法.intern 方法会从字符串常量池中查询当前字符串是否存在…
执行以下代码 String a1=new String("abc");       String a2=new String("abc");       System.out.println(a1==a2);       System.out.println(a1==a2.intern());       System.out.println("abc"==a2.intern());       System.out.println(a1.int…
字符串常量池在jdk升级过程中发生了一些变化 在JDK1.6中,它在方法区中,属于“永久代”. 在JDK1.7中,它被移除方法区,放在java堆中. 在JDK1.8中,取消了“永久代”,将常量池放在元空间,与堆独立 jdk1.6中,intern()方法会把首次遇到的字符串示例复制到永久代中,返回的也是永久代中这个字符串实例的引用 jdk1.6以后,对于实例,intern()方法不会再复制实例,只是在常量池中记录首次出现的实例引用,对于字符串仍然是加入字符串常量 比如下面这段代码,这段代码在常量池…
https://blog.csdn.net/soonfly/article/details/70147205 在翻<深入理解Java虚拟机>的书时,又看到了2-7的 String.intern()返回引用的测试. 其实要搞明白String.intern(),我总结了下面几条规则: 一.new String都是在堆上创建字符串对象.当调用 intern() 方法时,编译器会将字符串添加到常量池中(stringTable维护),并返回指向该常量的引用.  二.通过字面量赋值创建字符串(如:Stri…
转自:https://tech.meituan.com/in_depth_understanding_string_intern.html 深入解析String#intern john_yang ·2014-03-06 17:10 引言 在 JAVA 语言中有8中基本类型和一种比较特殊的类型String.这些类型为了使他们在运行过程中速度更快,更节省内存,都提供了一种常量池的概念.常量池就类似一个JAVA系统级别提供的缓存. 8种基本类型的常量池都是系统协调的,String类型的常量池比较特殊.…
在Java虚拟机(以下简称JVM)中,类包含其对应的元数据,比如类的层级信息,方法数据和方法信息(如字节码,栈和变量大小),运行时常量池,已确定的符号引用和虚方法表. 在过去(当自定义类加载器使用不普遍的时候),类几乎是“静态的”并且很少被卸载和回收,因此类也可以被看成“永久的”.另外由于类作为JVM实现的一部分,它们不由程序来创建,因为它们也被认为是“非堆”的内存. 在JDK8之前的HotSpot虚拟机中,类的这些“永久的”数据存放在一个叫做永久代的区域.永久代一段连续的内存空间,我们在JVM…
引言 什么都先不说,先看下面这个引入的例子: public static void test4(){ String str1 = new String("SEU") + new String("Calvin"); System.out.println(str1.intern() == str1); System.out.println(str1 == "SEUCalvin"); } 再将上面的例子加上一行代码: public static voi…
参考:https://www.jianshu.com/p/0d1c003d2ff5 String.intern() String.intern()是native方法,底层调用c++中的StringTable:intern方法. 当调用intern方法是,如果常量池已经存在该字符串,则返回池中字符串. 否则将此字符串添加到常量池中,并返回字符串的引用. package com.ctrip.ttd.whywhy; class Test { public static void main(String…
1. 首先String不属于8种基本数据类型,String是一个对象. 因为对象的默认值是null,所以String的默认值也是null:但它又是一种特殊的对象,有其它对象没有的一些特性. 2. new String()和new String(“”)都是申明一个新的空字符串,是空串不是null: 3. String str=”kvill”:String str=new String (“kvill”);的区别: 在这里,我们不谈堆,也不谈栈,只先简单引入常量池这个简单的概念. 常量池(const…
在java中有constantPool常量池,常量池里存放的是类,方法,接口的等常量,而对于存放字符串常量通常存放的符号链接Symbol 或者真实的String的对象的引用. 我们来看一段简单的代码和反编译字节码 public class test { public static void main(String[] args) { String test = "test"; } } Constant pool: #1 = Class #2 // test #2 = Utf8 test…
Java的 String类有个有意思的public方法: public String intern() 返回标准表示的字符串对象.String类维护私有字符串池. 调用此方法时,如果字符串池已经包含等于此字符串对象的字符串(通过equals方法确定), 则返回池中的字符串. 否则,将此String对象添加到池中,并返回对此String对象的引用. 这个功能为String提供了字符串池,我们可以使用它来优化内存. 但是,这有一个缺点:在OpenJDK中,String.intern()是本地方法,它…
1 简介 String.intern()是JDK一早就提供的native方法,不由Java实现,而是底层JVM实现,这让我们对它的窥探提高了难度.特别是在Oracle收购了Sun公司后,源代码不开源了,更无法深入研究了.但我们还是有必要尽量地去探索. 本文将主要讲解一下String.intern()方法的原理.特点,并介绍一个新奇的应用. 2 String的池化 方法intern()的作用就是将String池化,这个池是String的常量池.不同版本的JDK有不同的实现. 2.1 不同实现与不同…
1.String类型“==”比较样例代码如下:package com.luna.test;public class StringTest { public static void main(String[] args) { String str1 = "todo"; String str2 = "todo"; String str3 = "to"; String str4 = "do"; String str5 = str3…
有一段这样的代码: for (int i = 0; i < 10000000; i++) { ("bluedavy" + i).intern(); if(i % 100 == 0) Thread.sleep(1); } 大家可以分别用这段代码在JDK 6里和JDK 7里跑跑看看,会有什么不同. 上面的代码在JDK 7里执行时比JDK 6将会更多的触发Young GC和Full GC,原因请见这段描述: In JDK 7, interned strings are no longe…
本文转载自:深入解析String#intern 引言 在 JAVA 语言中有8中基本类型和一种比较特殊的类型String.这些类型为了使他们在运行过程中速度更快,更节省内存,都提供了一种常量池的概念.常量池就类似一个JAVA系统级别提供的缓存. 8种基本类型的常量池都是系统协调的,String类型的常量池比较特殊.它的主要使用方法有两种: 直接使用双引号声明出来的String对象会直接存储在常量池中. 如果不是用双引号声明的String对象,可以使用String提供的intern方法.inter…
1.字符串常量池 每创建一个字符串常量,JVM会首先检查字符串常量池,如果字符串已经在常量池中存在,那么就返回常量池中的实例引用.如果字符串不在池中,就会实例化一个字符串放到字符串池中.常量池提高了JVM性能和内存开销 2.用new 的方式创建字符串 new方式创建字符串,会先检查常量池中是否有相同值的字符串.如果有,则拷贝一份到堆中,然后返回堆中的地址.如果没有,则在堆中创建一份,然后返回堆中的地址. 3.String Table String Table存放的是string的cache ta…
目录 简介 intern简介 intern和字符串字面量常量 分析intern返回的String对象 分析实际的问题 G1中的去重功能 总结 简介 StringTable是什么?它和String.intern有什么关系呢?在字符串对象的创建过程中,StringTable有起到了什么作用呢? 一切的答案都在本文中,快来看看吧. intern简介 intern是String类中的一个native方法,所以它底层是用c++来实现的.感兴趣的同学可以去查看下JVM的源码了解更多的内容. 这里我们主要谈一…
目录 简介 String.intern和G1字符串去重的区别 String.intern的性能 举个例子 简介 String对象有个特殊的StringTable字符串常量池,为了减少Heap中生成的字符串的数量,推荐尽量直接使用String Table中的字符串常量池中的元素. 那么String.intern的性能怎么样呢?我们一起来看一下. String.intern和G1字符串去重的区别 之前我们提到了,String.intern方法会返回字符串常量池中的字符串对象的引用. 而G1垃圾回收器…
intern()方法设计的初衷,就是重用String对象,以节省内存消耗. JDK1.6以及以前版本中,常量池是放在 Perm 区(属于方法区)中的,熟悉JVM的话应该知道这是和堆区完全分开的. 使用引号声明的字符串都是会直接在字符串常量池中生成的,而 new 出来的 String 对象是放在堆空间中的.所以两者的内存地址肯定是不相同的,即使调用了intern()方法也是不影响的. JDK1.7后,常量池被放入到堆空间中,这导致intern()函数的功能不同.public String inte…