- 浏览: 341999 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (212)
- spring (21)
- design pattern(java) (12)
- linux-shell (28)
- java-thread (20)
- java-collection (6)
- java-reflect (9)
- mysql (11)
- java-io (7)
- java-util&lang&io (3)
- algorithm (3)
- interview (2)
- tools-eclipse (2)
- tools-maven (1)
- web-script (1)
- java组建 (13)
- 博客收藏 (1)
- 架构设计与实践 (10)
- active-mq (6)
- java-jvm&性能&原理 (27)
- tomcat (2)
- flume (1)
- serialization (2)
- git (1)
- cache&redis (8)
- guava (1)
- zookeeper (3)
- socket&tcp&udp&http (6)
- test (1)
最新评论
-
bbls:
有用有用有用
java-jvm-jstack-(监视器和锁的概念) -
王新春:
小侠有点帅哦 写道此流怎么关闭新春这个实现 可以不关闭的,哈哈 ...
源码剖析之java.io.ByteArrayOutputStream -
小侠有点帅哦:
此流怎么关闭新春
源码剖析之java.io.ByteArrayOutputStream -
cumt168:
写的很好为什么初始化参数,年轻代-Xmn10M def new ...
jvm之内存申请过程分析 -
ronin47:
应该是跟共享域名思路差不多,根据cookie的key作判断
跨域:一种通过服务端解决跨域的实现
----------~开篇分享一句话:【纸上得来终觉浅,绝知此事要躬行】~---------------------------------------
String.intern() 方法会自动把String放到jvm的PSPermGen的常量区。
关于String.intern()的使用需要注意以下两点:
1、对于日常工作中List中的数据对象,如果对象的某个属性是String,比如性别,国家等重复率较高的字符串取值,如果放入常量区,会节省大量的内存空间。
2、jvm的常量池的的搜索比较慢,速度甚至比ConcurrentHashMap 慢了不少。
证明:
JVM参数配置:
结果:
testIntern time :2657
testIntern memory:1.8076171875M
eden space 86272K, 3% used [0x00000000f9c00000,0x00000000f9f4b3f0,0x00000000ff040000)
结果:
Exception in thread "main" [Full GC [PSYoungGen: 81920K->0K(92160K)] [PSOldGen: 102400K->188K(102400K)] 184320K->188K(194560K) [PSPermGen: 3048K->3048K(21248K)], 0.0530156 secs] [Times: user=0.05 sys=0.00, real=0.05 secs]
java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.lang.StringBuilder.toString(StringBuilder.java:430)
at com.mystore.core.common.TestMemory.testCommon(TestMemory.java:85)
at com.mystore.core.common.TestMemory.main(TestMemory.java:13)
结果:testIntern time :2006
testCurrentHashMap memory:1.9482421875
eden space 85888K, 3% used [0x00000000f9c00000,0x00000000f9f477f8,0x00000000fefe0000)
结论:
对比testCommon 和 testIntern 说明testCommon 会占用较多的堆区内存,testIntern 会导致常量区会有微量的增长(仅仅1000个字符常量而已)
对比testIntern 和 testCurrentHashMap ,testCurrentHashMap 在性能方面有优势,更为需要关注的是testCurrentHashMap的内存分配在了堆区,而testIntern 分配在了常量区,一般情况下 堆区的老年代要比持久代要大的多,所以从gc的角度来说,更应该使用testCurrentHashMap 的方式。不好的一点是 testCurrentHashMap 中的常量会一直增长没有过期 策略,而常量池则会在full gc 的时候自动做清理。testCurrentHashMap 优化的方向是 使用带缓存并且线程安全的Map,比如guava的缓存Map
参考: 性能对比参见 http://stackoverflow.com/questions/10624232/performance-penalty-of-string-intern
String.intern() 方法会自动把String放到jvm的PSPermGen的常量区。
关于String.intern()的使用需要注意以下两点:
1、对于日常工作中List中的数据对象,如果对象的某个属性是String,比如性别,国家等重复率较高的字符串取值,如果放入常量区,会节省大量的内存空间。
2、jvm的常量池的的搜索比较慢,速度甚至比ConcurrentHashMap 慢了不少。
证明:
JVM参数配置:
-Xmx200M -Xms200M -Xmn100M -XX:SurvivorRatio=8 -XX:+PrintGCDetails
public static long times = 10000000L; public static void testIntern() { System.gc(); List<String> list = new ArrayList<String>(); long l = System.currentTimeMillis(); for (int i = 0; i < times; i++) { list.add(("A" + (i % 1000)).intern()); } long ll = System.currentTimeMillis(); System.out.println("testIntern time :" + (ll -l)); System.gc(); System.out.println("testIntern:" + (wrapM(Runtime.getRuntime().totalMemory()) - wrapM(Runtime .getRuntime().freeMemory()))); }
结果:
testIntern time :2657
testIntern memory:1.8076171875M
eden space 86272K, 3% used [0x00000000f9c00000,0x00000000f9f4b3f0,0x00000000ff040000)
public static void testCommon() { System.gc(); List<String> list = new ArrayList<String>(); long l = System.currentTimeMillis(); for (int i = 0; i < times; i++) { list.add(("A" + (i % 1000))); } long ll = System.currentTimeMillis(); System.out.println("testIntern time :" + (ll -l)); System.gc(); System.out.println("testCommon memory:" + (wrapM(Runtime.getRuntime().totalMemory()) - wrapM(Runtime .getRuntime().freeMemory()))); }
结果:
Exception in thread "main" [Full GC [PSYoungGen: 81920K->0K(92160K)] [PSOldGen: 102400K->188K(102400K)] 184320K->188K(194560K) [PSPermGen: 3048K->3048K(21248K)], 0.0530156 secs] [Times: user=0.05 sys=0.00, real=0.05 secs]
java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.lang.StringBuilder.toString(StringBuilder.java:430)
at com.mystore.core.common.TestMemory.testCommon(TestMemory.java:85)
at com.mystore.core.common.TestMemory.main(TestMemory.java:13)
public static void testCurrentHashMap() { System.gc(); List<String> list = new ArrayList<String>(); long l = System.currentTimeMillis(); for (int i = 0; i < times; i++) { list.add((StringCache.get("A" + (i % 1000)))); } long ll = System.currentTimeMillis(); System.out.println("testIntern time :" + (ll -l)); System.gc(); System.out.println("testCurrentHashMap memory:" + (wrapM(Runtime.getRuntime().totalMemory()) - wrapM(Runtime .getRuntime().freeMemory()))); } private static double wrapM(long length) { return length / 1024 / 1024.0; } static class StringCache { private static ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>(10000); public static String get(String str){ if(null == str){ return null; } String ret = map.get(str); if(null == ret){ map.putIfAbsent(str, str); ret = map.get(str); } return ret; } }
结果:testIntern time :2006
testCurrentHashMap memory:1.9482421875
eden space 85888K, 3% used [0x00000000f9c00000,0x00000000f9f477f8,0x00000000fefe0000)
结论:
对比testCommon 和 testIntern 说明testCommon 会占用较多的堆区内存,testIntern 会导致常量区会有微量的增长(仅仅1000个字符常量而已)
对比testIntern 和 testCurrentHashMap ,testCurrentHashMap 在性能方面有优势,更为需要关注的是testCurrentHashMap的内存分配在了堆区,而testIntern 分配在了常量区,一般情况下 堆区的老年代要比持久代要大的多,所以从gc的角度来说,更应该使用testCurrentHashMap 的方式。不好的一点是 testCurrentHashMap 中的常量会一直增长没有过期 策略,而常量池则会在full gc 的时候自动做清理。testCurrentHashMap 优化的方向是 使用带缓存并且线程安全的Map,比如guava的缓存Map
参考: 性能对比参见 http://stackoverflow.com/questions/10624232/performance-penalty-of-string-intern
发表评论
-
垃圾回收算法详解
2017-05-17 16:42 498可回收对象的判定【收藏,非原创】 讲算法之前,我们先要 ... -
垃圾回收算法&STOP The World
2017-05-15 11:50 662目前所有的新生代gc都是需要STW的: Seria ... -
java-jvm-jhat
2017-05-14 21:04 557功能:可以分析jmap dump下的hprof文件 一般 ... -
java-jvm-jinfo
2017-05-14 20:57 687jinfo: 1、输出 当前java进程启动的相关配置信息 ... -
jvm-gc 日志解读【转载】
2017-05-14 17:34 485转载自:http://ifeve.com/useful-j ... -
大量异常带来性能的影响
2017-05-09 19:08 671感受大量构造异常带来的性能影响: package com; ... -
iotop&iostat (load高 IO高的问题排查)
2017-04-27 20:40 2113目标:使用iotop&top&jstack ... -
java-jvm-jstack-(监视器和锁的概念)
2017-04-06 16:52 6498下面这段jstack的栈信息里,有一个死锁 其中: T ... -
java-jvm-jstack-线程状态
2017-03-31 14:42 2615常见的线程状态: RUNNABLE:正在执行的线程 注 ... -
java-jvm-cpu (cpu)高问题排查
2017-03-28 21:07 33341、通过top命令发现 cpu高的进程 根据top命令, ... -
java-jvm-jstack
2016-08-05 11:07 2197jstack用于打印出给定的java进程ID或core fi ... -
java-jvm好文收集
2016-08-05 10:50 475非常详细GC学习笔记http://blog.csdn.ne ... -
java-jvm-jstat
2016-08-05 10:30 657stat用于监控基于HotSpot ... -
java-jvm-jmap(高内存排查)
2016-07-29 13:51 3810功能:打印出某个java进程(使用pid)内存内的,所有‘对象 ... -
java-jvm-jps
2016-07-29 13:42 472jsp -q 只显示pid,不显示class名称,jar文件 ... -
OutOfMemoryError溢出
2016-03-29 23:29 841Java堆溢出: java.lang.OutOfMemor ... -
垃圾回收器的分类
2016-03-29 22:23 733基础: 串行收集器: DefNew:是使用-XX:+UseSe ... -
ClassLoader-线程上下文类加载器
2015-04-16 10:54 1196线程上下文类加载器 :http://blog.csdn.net ... -
ClassLoader-热替换
2015-04-05 20:27 2750https://www.ibm.com/developer ... -
ClassLoader-学习
2015-04-05 19:03 1070相关文章:https://www.ib ...
相关推荐
`,JVM会在常量池中查找是否存在"abc",如果存在则直接引用该字符串;如果不存在,则创建一个新的字符串对象并将其放入常量池。这种方式创建的字符串,一旦创建便不会改变,且可以共享。 而使用new关键字创建字符串...
通过上述介绍可以看出,JVM中的各种常量池对于优化程序性能、管理内存资源以及提高代码的可读性和可维护性等方面都有着重要的作用。理解和掌握这些常量池的工作原理,对于编写高效、稳定的Java应用程序是非常有益的...
Java String 字符串常量池解析 Java 中的字符串常量池是一种为了提高性能和减少内存开销的机制。它是 JVM 实例化字符串常量时进行的一些优化,主要是为了减少字符串对象的创建和存储。 字符串常量池的设计思想是...
在Java中,内存主要分为四个区域:寄存器、栈、堆和方法区(包括常量池)。以下是这四个区域的详细说明: 1. **寄存器**: 这是计算机硬件的一部分,用于存储非常快速访问的数据。在Java中,寄存器主要由JVM直接管理...
**StringTable(字符串常量池)详解** 在Java编程语言中,`StringTable`是一个重要的概念,它涉及到字符串对象的创建、存储以及内存管理。理解`StringTable`的工作原理对于优化程序性能和节省内存资源至关重要。 #...
当我们调用一个String实例的intern()方法时,JVM会检查常量池中是否存在相同Unicode的字符串。如果存在,就返回该引用;如果不存在,就会在常量池中创建一个新的字符串并返回它的引用。 考虑以下代码: ```java ...
当我们创建一个字符串字面量,如`String s = "haha"`,JVM执行的虚拟机指令涉及到常量池。`ldc`指令从常量池中获取指定索引的`CONSTANT_String_info`条目,这里包含的是字符串"haha"的引用。然后,`astore_1`指令将...
在Java编程语言中,字符串常量池(String Constant Pool)是一个重要的概念,它与程序的内存管理和性能优化密切相关。理解这个概念对于任何Java开发者来说都至关重要。字符串常量池是Java虚拟机(JVM)在运行时为...
`这样的形式创建字符串时,JVM会首先检查常量池中是否存在`"Hello"`这个字符串。如果存在,则直接复用已有的对象;如果不存在,则在常量池中创建一个新的字符串对象,并返回其引用。 2. **字符串对象池**:通常所...
首先,字符串常量池位于JVM的永久代(Permanent Generation)中,这个区域在HotSpot VM的实现中由一个叫做StringTable的数据结构维护。StringTable本质上是一个哈希表,默认大小为1009。这个表在每个HotSpot VM实例...
数据类型决定了变量可以存储的值的种类和大小,而运行时常量池则是Java虚拟机(JVM)内存模型中的一个重要组成部分。 首先,让我们详细讨论Java的数据类型。Java的数据类型分为两大类:基本数据类型和引用数据类型...
这个方法的主要功能是检查当前字符串对象的值是否已经在Java虚拟机(JVM)的字符串常量池中存在。如果存在,它会返回常量池中的引用;如果不存在,它会将当前字符串的引用放入常量池,并返回这个新添加的引用。 在...
字符串常量池存放在堆中,包括 String 对象执行 intern() 方法后存放的地方和双引号直接引用的字符串。运行时常量池存放在方法区,属于元空间,是类加载后的一些存储区域,大多数是类中 constant_pool 的内容。类...
Java中的常量池是Java虚拟机(JVM)中的一种机制,用于存储编译期常量和运行期常量。常量池是JVM中的一种重要机制,它可以将常量存储在内存中,并提供快速的访问和共享机制。 Java中的常量池有三种形态:静态常量池...
在Java虚拟机(JVM)中,`String.intern()` 是一个非常特殊且重要的方法,它与字符串常量池紧密相关。字符串常量池是一种内存优化机制,存储了程序中所有的字符串字面值和通过 `intern()` 方法添加的字符串。这个池...
3. **运行时常量池优化**: - **静态常量合并**:减少常量池中的条目数量,提高内存利用率。 - **动态加载**:延迟加载非必须的类和资源,降低启动时的内存压力。 三、垃圾收集与内存管理 1. **垃圾收集算法**:...
字符串常量池是在运行时动态维护的,当需要使用字符串时,JVM首先会在字符串常量池中查找是否存在该字符串。如果存在,就直接使用;如果不存在,会创建一个新的字符串实例并放入池中,确保池中没有重复的字符串。 ...
在Java虚拟机(JVM)中,StringTable扮演着至关重要的角色,它是字符串常量池的实现,存放着程序中所有的字符串字面量。本文将详细探讨StringTable的原理、特点以及相关优化策略。 **StringTable的特性与作用** 1....
2. 对象池技术:减少频繁创建和销毁对象带来的开销,例如String Pool。 3. 分布式缓存:使用如Redis等缓存系统,减轻JVM内存压力。 4. 使用G1垃圾收集器:G1能实现并行、并发且低延迟的垃圾收集,适合大型应用。 ...