文章目录 1.什么是StringTable 2.java中字符串拼接的秘密 3.intern()方法与StringTable调优 3.1 intern方法结束 3.2 Stringtable参数调优 4 但是或许很多人还并不知道什么是StringTable。StringTable也可称为StringPool,是jvm在1.7之后,在堆内存中分配的一块区域,用于存放常用的字符串。 StringTable实际上是一个固定大小的HashTable。因此被称为StringTable。其默认大小为60013。 3.2 Stringtable参数调优 那么对于StringTable,实际上如果一个程序中的StringTable过大,将会导致不少问题: //-XX:+PrintStringTableStatistics 这样就会导致对StringTable检索会慢。我们现在对Stringtable进行优化,调整StringTableSize=10000000 ?
使用-XX:StringTablesize可设置StringTable的长度 在JDK6中StringTable是固定的,就是1009的长度,所以如果常量池中的字符串过多就会导致效率下降很快,StringTablesize 设置没有要求 在JDK7中,StringTable的长度默认值是60013,StringTablesize设置没有要求 在JDK8中,StringTable的长度默认值是60013,StringTable 可以设置的最小值为1009 代码示例 测试不同 StringTable 长度下,程序的性能 /** * -XX:StringTableSize=1009 */ public class StringTest2 Java8元空间,字符串常量在堆 StringTable 为什么要调整? 为什么要调整位置? XX:+PrintGCDetails 在 PSYoungGen 区发生了垃圾回收 Number of entries 和 Number of literals 明显没有 100000 以上两点均说明 StringTable
使用-XX:StringTablesize可设置StringTable的长度 在jdk6中StringTable是固定的,就是1009的长度,所以如果常量池中的字符串过多就会导致效率下降很快。 StringTablesize设置没有要求 在jdk7中,StringTable的长度默认值是60013,StringTablesize设置没有要求 在JDK8中,设置StringTable长度的话, Java8元空间,字符串常量在堆 StringTable为什么要调整? StringTable的垃圾回收 public class StringGCTest { /** * -Xms15m -Xmx15m -XX:+PrintGCDetails
package com.jvm; import org.junit.Test; /** * 常量池StringTable的详解 * 可以使用该命令查看,当前类的字节码常量池信息 * javap
序 本文主要研究一下jvm的StringTable及SymbolTable jvm_memory_overview.jpg StringTable及SymbolTable JDK的变动 在java7 Linking)根据class元数据中的constant pool table创建的,因而称为Runtime Constant Pool;这部分属于metaspcae,在native memory中 查看StringTable / # jcmd 1 VM.stringtable 1: StringTable statistics: Number of buckets : 65536 = 524288 位于heap中(java7+),而SymbolTable则在native memory中;使用jcmd pid VM.stringtable可以在运行时查看StringTable;使用jcmd pid statistics;使用jcmd pid VM.native_memory输出的Symbol部分包含了heap中StringTable(interned String)及non heap中的SymbolTable
简介 StringTable是什么?它和String.intern有什么关系呢?在字符串对象的创建过程中,StringTable有起到了什么作用呢? 一切的答案都在本文中,快来看看吧。 StringTable中的String。 如果StringTable中没有相同的对象,那么这个String对象将会被加入StringTable,并返回这个String对象的引用。 在JDK6中,StringTable是存放在方法区中的,而方法区是放在永久代中的。 在JDK7之后,StringTable已经被转移到了java Heap中了,调用intern方法的时候,StringTable可以直接将该String对象加入StringTable,从而指向的是同一个对象
这是因为,java中字符串有字符串常量池StringTable,这个将在后续介绍。需要说明的是,a b 实际上都是指向常量池中的同一内容。 */ public native String intern(); 从注释中可以看出,这个方法的作用就是,如果常量池中存在此字符串,则返回常量池中字符串的引用,如果没有该字符串,则将该值加入StringTable 关于StringTable常量池我们将再后续介绍。
既然在前面章节说到java中的字符串相加,实际上是执行的StringBuilder的append操作,那么现在就对StringBuilder的相关源码进行解读。
分析完StringBuilder,然后再聊StringBuffer就简单多了。因为StringBuffer同样也是继承了AbstractStringBuilder。
简介 StringTable是什么?它和String.intern有什么关系呢?在字符串对象的创建过程中,StringTable有起到了什么作用呢? 一切的答案都在本文中,快来看看吧。 StringTable中的String。 如果StringTable中没有相同的对象,那么这个String对象将会被加入StringTable,并返回这个String对象的引用。 在JDK6中,StringTable是存放在方法区中的,而方法区是放在永久代中的。 在JDK7之后,StringTable已经被转移到了java Heap中了,调用intern方法的时候,StringTable可以直接将该String对象加入StringTable,从而指向的是同一个对象
第 13 章 StringTable 1、String 的基本特性 1.1、String 概述 String 的概述 为什么 JDK9 改变了 String 的结构 官方文档 http:// 使用-XX:StringTablesize可设置StringTable的长度 在JDK6中StringTable是固定的,就是1009的长度,所以如果常量池中的字符串过多就会导致效率下降很快,StringTablesize 设置没有要求 在JDK7中,StringTable的长度默认值是60013,StringTablesize设置没有要求 在JDK8中,StringTable的长度默认值是60013,StringTable 长度 JVM 参数 -XX:StringTableSize=6666 jinfo 查看变量值 jpsjinfo -flag StringTableSize 进程id 测试不同 StringTable Java8元空间,字符串常量在堆 2.2、为什么要调整 String 位置 StringTable 为什么要调整? 为什么要调整位置?
在java8中,对于字符串拼接的操作还引入了一个新的类就是StringJoiner,这个类的作用就是提供了一种快捷的字符串拼接的模板方法。
当StringTable里没有某一个字符串的时候,调用intern的时候,就会把这个字符串添加到StringTable里去。 Java在加载字符串常量的时候会调用一遍intern,那么StringTable里就会留下这个hotspot默认创建的字符串。 好了。回到原问题。 h = new String("hw"); 这条语句,"hw"是一个常量字符串,实际上,已经做过一次intern了,StringTable里保留的是hotspot默认创建的字符串。 所以h2和h1会是相等的,都是StringTable里的这个默认字符串。 而s3因为是计算得来的,不是字符串常量,所以手动调用s3.intern()时,StringTable里留下的就是s3。 再对s4赋值时,由于StringTable里已经有值了,所以不必再创建一次String对象,直接使用StringTable里的那个值就好了,其实就是s3,因此s3与s4是相同的对象。
串池简介 我们首先来简单介绍一下串池: 串池的本质是一个哈希表,其中的每个元素都是唯一的 我们在这里稍微解释一下为什么StringTable会移动到堆中: jdk7中将StringTable放到了堆空间中 字符串延迟加载 在这里我们再次强调一下StringTable中元素的加载原则: StringTable中的值只会加载一次,不会重复加载 存放在常量池的值在运行时不会加载,只有在第一次运行时才会加载到StringTable 中,所以将其复制一份放入StringTable,并将StringTable里面的"ab"返回回去 // 这时s和StringTable里面的"ab"是不一样的! 里存在"ab",所以将StringTable里面的ab返回给s2即可 // 目前s2和x属于StringTable里面的ab,s属于堆里面的ab String s2 = 里面不存在,会将堆中s的字符串做成一个引用直接放入StringTable里面,再将StringTable的值返回 // 这时s,s2,x均属于堆里面的ab,不过s2是堆里的ab,s,x为
具体看下面测试方法的注释 导致两个方法中最后一行System.out.println(“ab” == s) 输出不同 测试一:执行String s1 = s.intern() 前放入”ab” //最终串池中对象StringTable s = new String("a") + new String("b"); //简化等同于 String s = new String("ab"); //*****线程此时串池中对象StringTable ab" 之前代码行中未出现常量 "ab" System.out.println("ab" == s1); //true 都是串池中的常量对象 ab //****此时串池中对象StringTable void main(String[] args) { String s = new String("a") + new String("b"); //*****线程此时串池中对象StringTable ["a", "b"] String s1 = s.intern(); //拷贝一份s对象放入 //*****线程此时串池中对象StringTable["a", "b", "ab"]
if (str == NULL) return NULL; oop string = JNIHandles::resolve_non_null(str); oop result = StringTable ::intern方法 C++文件src/hotspot/share/classfile/stringTable.cpp oop StringTable::intern(oop string, TRAPS hash, CHECK_NULL); } 继续看下StringTable::the_table()->do_intern方法 C++文件src/hotspot/share/classfile/stringTable.cpp oop StringTable::do_intern(Handle string_or_null_h, jchar* name, int len, 最后,StringTable::do_intern方法调用stc.get_return()返回结果,即,如果有对应的string,则返回对应的string,如果没有,则返回原string。
),也就是说在堆中的某些字符串实例被这个 StringTable 引用之后就等同被赋予了”驻留字符串”的身份。 这个StringTable在每个 HotSpot VM 的实例只有一份,被所有的类共享。 str4是在运行的时候调用 intern() 函数,返回StringTable中 def 的引用值,如果没有就将str2的引用值添加进去,在这里,StringTable中已经有了 def 的引用值了,所以返回上面在 new str2的时候添加到StringTable中的 def 引用值, 最后str5在解析的时候就也是指向存在于StringTable中的 def 的引用值。 中; 最后在解析阶段,要把运行时常量池中的符号引用替换成直接引用,那么就直接查询StringTable,保证StringTable里的引用值与运行时常量池中的引用值一致,大概整个过程就是这样了。
oam; if (str == NULL) return NULL; oop string = JNIHandles::resolve_non_null(str); oop result = StringTable return (jstring) JNIHandles::make_local(env, result); JVM_END 可以看出,字符串常量池在JVM内部就是一个HashTable,也就是上面代码中的StringTable 根据StringTable::intern方法跟下去,就可以跟到下面这段代码中,如果找到了就直接返回found_string,如果没有找到,就将当前的字符串加入到HashTable中,然后再返回。 oop StringTable::intern(Handle string_or_null, jchar* name, int len, TRAPS) { oop added_or_found; { MutexLocker ml(StringTable_lock, THREAD); // Otherwise, add to symbol
等名字前缀自定义字符串值存储方式,示例如下: import sqlite var sqlConnection = sqlite(":memory:") if( not sqlConnection.existsTable("stringTable ") ){ sqlConnection.exec( "create table stringTable(blobString,utf8String,utf16String);") } sqlConnection.prepare("insert into stringTable values (@blobString,@utf8String,@utf16String);" ). io.open(); for rowid,blobString,utf8String,utf16String in sqlConnection.each("select rowid,* from stringTable
在HotSpot VM里实现的string pool功能的是一个StringTable类,它是一个Hash表,默认值大小长度是1009;这个StringTable在每个HotSpot VM的实例只有一份 字符串常量由一个一个字符组成,放在了StringTable上。 在JDK6.0中,StringTable的长度是固定的,长度就是1009,因此如果放入String Pool中的String非常多,就会造成hash冲突,导致链表过长,当调用String#intern( )时会需要到链表上一个一个找,从而导致性能大幅度下降; 在JDK7.0中,StringTable的长度可以通过参数指定: -XX:StringTableSize=66666 1.3:字符串常量池里放的是什么 在解析阶段,会把符号引用替换为直接引用,解析的过程会去查询字符串常量池,也就是我们上面所说的StringTable,以保证运行时常量池所引用的字符串与字符串常量池中是一致的。