我在本地用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内存泄漏的更多相关文章

  1. java虚拟机学习-JVM内存管理:深入Java内存区域与OOM(3)

    概述 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝又 ...

  2. 《成神之路-基础篇》JVM——Java内存模型(已完结)

    Java内存模型 本文是<成神之路系列文章>的第一篇,主要是关于JVM的一些介绍. 持续更新中 Java内存模型 JVM内存结构 VS Java内存模型 VS Java对象模型(Holli ...

  3. iOS开发:MKMapView地图内存持续增加的释放解决办法

    内存持续增加的释放解决办法 最近修改一个用到MKMapView的项目,内存一直占用过多,每次拖拽地图时还会增加占用,且一直无法释放. 经过两天的排查,最后锁定是创建的self.map对象在加载地图的时 ...

  4. [jvm]java内存模型

    一.java内存模型 Java虚拟机规范中试图定义一种Java内存模型(Java Memory Model,JMM)来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一 ...

  5. 故障重现(内存篇2),JAVA内存不足导致频繁回收和swap引起的性能问题

    背景起因: 记起以前的另一次也是关于内存的调优分享下   有个系统平时运行非常稳定运行(没经历过大并发考验),然而在一次活动后,人数并发一上来后,系统开始卡. 我按经验开始调优,在每个关键步骤的加入如 ...

  6. 【转】Java内存管理:深入Java内存区域

    转自:http://www.cnblogs.com/gw811/archive/2012/10/18/2730117.html 本文引用自:深入理解Java虚拟机的第2章内容 Java与C++之间有一 ...

  7. Java内存管理:深入Java内存区域

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 对于从事C和C++程序开发的开发人员来说,在内存管理领域,他们既是拥有最高权力的皇帝 ...

  8. JVM Java 内存区域透彻分析(转)

    出处:  Java 内存区域透彻分析  Java8内存模型—永久代(PermGen)和元空间(Metaspace) 这篇文章主要介绍Java内存区域,也是作为Java虚拟机的一些最基本的知识,理解了这 ...

  9. JVM内存管理:深入Java内存区域与OOM

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝 ...

随机推荐

  1. python 动态导入模块、断言

    断言: 类似与判断,后面的程序依赖前面的,可以加一个断言,断言成功继续执行.断言失败报错停止执行. a = 'abc' assert type(a) is str print('yes') asser ...

  2. sql server性能分析--执行sql次数和逻辑次数

    目前在做一个项目优化时,想通过数据库层分析sql server系统性能,查了一下网上代码,修改了一下标题和DMVs代码,以下代码可以用来分析系统运行一段时间后,那些语句是系统忙的sql语句.做为参考. ...

  3. yjh_study_command

    1.show current user in oralce ansower:show user 2.search  name of table  in current user model. answ ...

  4. oracle模糊搜索避免使用like,替换为instr()

    oracle中instr()函数用法 instr(name,'张三')>0  相当于  name like '%张三%' instr(name,'张三')=1  相当于  name like ' ...

  5. JS interview loop code

    //九九乘法表 document.write("<table width='600' border=0'>"); for(var i=1; i<=9; i++){ ...

  6. OC 类 的声明

    Student.h // @interface代表声明一个类 // : 代表继承 @interface Student : NSObject { // 成员变量要定义在下面的大括号中{} int ag ...

  7. nautilus命令

    nautilus 是图形程式效果是以当前用户打开图形界面所以如果想以root打开图形界面使用时记得先切为root,sudo没有用的

  8. 【[HAOI2011]Problem c】

    好题啊 先考虑一些如何判掉无解的情况 我们开一个桶,存一下每个编号有多少个人必须选,之后做一个后缀和,之后我们扫一遍,如果一旦有一个后缀和\(pre[i]\)超过\(n-i+1\)就不合法了,因为我们 ...

  9. Node.js使用MySQL数据库中对RowDataPacket对象的使用

    使用Node.js开发使用MySQL数据库的网站,在查询后返回一RowDataPacket类型的对象 原先使用toString()方法一直得到仅为object的字符串,无法使用 后思考,才发现忽略了其 ...

  10. 作为PHP开发者请务必了解Composer

    Composer是一个非常流行的PHP包依赖管理工具,已经取代PEAR包管理器,对于PHP开发者来说掌握Composer是必须的. 对于使用者来说Composer非常的简单,通过简单的一条命令将需要的 ...