Jackson 触发的String.intern() bug, 导致内存持续增加,JVM-Java内存泄漏
我在本地用Jackson可以复现这个问题了。
import java.io.IOException;
import java.util.Map;
import java.util.Random;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Test {
public static void main(String[] args) throws IOException {
// JsonFactory factory = new JsonFactory().disable(JsonFactory.Feature.INTERN_FIELD_NAMES);
// ObjectMapper om = new ObjectMapper(factory);
ObjectMapper om = new ObjectMapper(); Random random = new Random();
while (true) {
System.out.println("Press any key to continue");
System.in.read();
int key = random.nextInt();
System.out.println("Generated key: " + key);
Map<Integer, Boolean> desMap =
om.readValue(String.format("{\"%s\":\"true\"}", key), new TypeReference<Map<Integer, Boolean>>() {});
System.out.println("Read map: " + desMap);
}
}
}
这是我复现的代码,我每次产生一个随机的integer作为map的key,然后用objectMapper反序列化。然后我运行我的另外一个PrintStringTable的类,可以看到每次产生的Integer都会进入Constant Pool中
如果我把构造ObjectMapper的代码改成我注释掉的代码的话,不管产生多少随机Integer key,都不会进入Constant Pool
PrintStringTable类如下
import sun.jvm.hotspot.memory.StringTable;
import sun.jvm.hotspot.memory.SystemDictionary;
import sun.jvm.hotspot.oops.Instance;
import sun.jvm.hotspot.oops.InstanceKlass;
import sun.jvm.hotspot.oops.OopField;
import sun.jvm.hotspot.oops.TypeArray;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.tools.Tool;
public class PrintStringTable extends Tool {
public PrintStringTable() {
}
public static void main(String args[]) throws Exception {
if (args.length == 0 || args.length > 1) {
System.err.println("Usage: java PrintStringTable <PID of the JVM whose string table you want to print>");
System.exit(1);
}
PrintStringTable pst = new PrintStringTable();
pst.execute(args);
pst.stop();
}
@Override
public void run() {
StringTable table = VM.getVM().getStringTable();
table.stringsDo(new StringPrinter());
}
class StringPrinter implements StringTable.StringVisitor {
private final OopField stringValueField;
public StringPrinter() {
InstanceKlass strKlass = SystemDictionary.getStringKlass();
stringValueField = (OopField) strKlass.findField("value", "[C");
}
@Override
public void visit(Instance instance) {
TypeArray charArray = ((TypeArray) stringValueField.getValue(instance));
StringBuilder sb = new StringBuilder();
for (long i = 0; i < charArray.getLength(); i++) {
sb.append(charArray.getCharAt(i));
}
System.out.println("Address: " + instance.getHandle() + " Content: " + sb.toString());
}
}
}
需要用/{jdk_HOME}/lib/sa-jdi.jar进行编译和运行,运行参数是需要attach的pid
修改要点
protected JsonFactory factory = new JsonFactory().disable(JsonFactory.Feature.INTERN_FIELD_NAMES);
protected ObjectMapper mapper = new ObjectMapper(factory).setTimeZone(TimeZone.getDefault());
参考Oracle Java 官方文档
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/nmt-8.html
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr007.html (Native Memory Tracking)
Jackson 触发的String.intern() bug, 导致内存持续增加,JVM-Java内存泄漏的更多相关文章
- java虚拟机学习-JVM内存管理:深入Java内存区域与OOM(3)
概述 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝又 ...
- 《成神之路-基础篇》JVM——Java内存模型(已完结)
Java内存模型 本文是<成神之路系列文章>的第一篇,主要是关于JVM的一些介绍. 持续更新中 Java内存模型 JVM内存结构 VS Java内存模型 VS Java对象模型(Holli ...
- iOS开发:MKMapView地图内存持续增加的释放解决办法
内存持续增加的释放解决办法 最近修改一个用到MKMapView的项目,内存一直占用过多,每次拖拽地图时还会增加占用,且一直无法释放. 经过两天的排查,最后锁定是创建的self.map对象在加载地图的时 ...
- [jvm]java内存模型
一.java内存模型 Java虚拟机规范中试图定义一种Java内存模型(Java Memory Model,JMM)来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一 ...
- 故障重现(内存篇2),JAVA内存不足导致频繁回收和swap引起的性能问题
背景起因: 记起以前的另一次也是关于内存的调优分享下 有个系统平时运行非常稳定运行(没经历过大并发考验),然而在一次活动后,人数并发一上来后,系统开始卡. 我按经验开始调优,在每个关键步骤的加入如 ...
- 【转】Java内存管理:深入Java内存区域
转自:http://www.cnblogs.com/gw811/archive/2012/10/18/2730117.html 本文引用自:深入理解Java虚拟机的第2章内容 Java与C++之间有一 ...
- Java内存管理:深入Java内存区域
Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 对于从事C和C++程序开发的开发人员来说,在内存管理领域,他们既是拥有最高权力的皇帝 ...
- JVM Java 内存区域透彻分析(转)
出处: Java 内存区域透彻分析 Java8内存模型—永久代(PermGen)和元空间(Metaspace) 这篇文章主要介绍Java内存区域,也是作为Java虚拟机的一些最基本的知识,理解了这 ...
- JVM内存管理:深入Java内存区域与OOM
Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝 ...
随机推荐
- 全面了解 NOSQL
NoSQL被我们用得最多的当数key-value存储,想知道为什么要有NOSQL,就首先要明白传统关系SQL: 传统关系数据库的瓶颈 传统的关系数据库具有不错的性能,高稳定型,久经历史考验,而且使用简 ...
- canvas入门(一)
canvas是HTML 5中非常重要的一个标签,关于它的功能和使用方法在这我就不一一细谈了,毕竟网上相关知识太多,而且自认为如果是我总结那些知识会让读者看的更乱,所以我就不白费力气了,贴上链接:htt ...
- Python对数组的基本操作
# coding=utf-8创建并打印数组'''arr = ["aex", "bfe", "mpilgrim", "zddd&qu ...
- sql server性能分析--执行sql次数和逻辑次数
目前在做一个项目优化时,想通过数据库层分析sql server系统性能,查了一下网上代码,修改了一下标题和DMVs代码,以下代码可以用来分析系统运行一段时间后,那些语句是系统忙的sql语句.做为参考. ...
- day008-File文件
1. File 文件和目录路径名的抽象表示形式. 一个File类对象就代表了一个文件或文件夹. 1.1 File类的作用 用来操作硬盘上的文件或文件夹 绝对路径:一般是以盘符开始的,比如:C:/Jav ...
- 在Docker容器中安装jdk和spark
在Docker容器中安装jdk和spark 1.下载jdk和spark 可以使用迅雷等专业下载软件下载jdk和spark软件包,注意是linux版,这里直接给出下载地址: JDK下载地址 JDK进入后 ...
- 思维导图与Spring Batch
最近在学画图,又在复习Spring Batch.不解释,直接上图. 第三章,用XMind画的. 第五章,用iMindMap画的.
- 『看球笔记』20140208利物浦VS阿森纳,十字重剑与蜜蜂飞舞
红圈位置42%对58%的控球率,是不是觉得比分很不符?我们卖个关子,最后再说这个. 十字重剑 第一次任意球防守,俩后卫盯俩后卫,负责斯科特尔的是科斯切尔尼,而默特萨克盯图雷. ...
- Android仿QQ复制昵称效果
本文同步自http://javaexception.com/archives/76 背景: 这几天做一个复制文本的需求,突然看到QQ上复制昵称跟QQ号的效果,觉得很不错,就想要模仿一波,办法比较简单粗 ...
- Mvc5 控制器,视图简单说明
本系列会比Mvc4更详细.Mvc4记录或没记录的东西这里也会提到. 控制器 自动装配: 一般自动装配对于添加的时候比较好用 视图: 控制器返回的视图,其实就是一些静态的HTML.动态性不好,从控制器传 ...