当前位置: 首页 > 编程日记 > 正文

Java String.substring内存泄露?

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

String可以说是最常用的Java类型之一了,但是最近听说JDK6里面String.substring存在内存泄露的bug,伙惊呆!一起来看看到底是啥情况吧。

这个是可以导致Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 的代码:

public class TestGC {private String largeString = new String(new byte[100000]);String getString() {        return this.largeString.substring(0, 2);//在JDK6里会导致out of memory,在JDK7和8不会出现问题//        return new String("ab");//        return this.largeString.substring(0,2) + "";//JDK6下的解决方法,不会出现out of memory//        return new String(this.largeString.substring(0, 2));/JDK6下的解决方法,不会出现out of memory} public static void main(String[] args) {java.util.List<String> list = new java.util.ArrayList<String>();        for (int i = 0; i < 100000; i++) {TestGC gc = new TestGC();list.add(gc.getString());}System.out.println("over" + list.size());}
}

但是用JDK8运行,平安无事。注意,之前看的网上文章又说安装了JDK8,只需要在Eclipse里面选Compiler选项为JDK6就可以了,我实 验是不可以的,自己想想String是JDK里面rt.jar的类,就算是编译为JDK6的代码,运行的时候还是用的JDK8的String啊,所以无法 复现bug才是正常的。要复现,只能下载安装JDK6.

有人认为这个会out of memory是因为TestGC对象里面有很大largeString的对象,但是其实在调用getString方法后,TestGC对象完全可以被回收 的,largeString也可以回收,JVM的自动垃圾回收应该不会有bug吧,不然还得了!将getString方法改为直接返回一个String对 象,就可以看出,不会有问题。

现在来看看为什么JDK6里面,substring会导致错误呢。Ctrl+B(IDEA的查看源码快捷键点进去看下),代码如下

public String substring(int beginIndex, int endIndex) {    if (beginIndex < 0) {        throw new StringIndexOutOfBoundsException(beginIndex);}    if (endIndex > count) {        throw new StringIndexOutOfBoundsException(endIndex);}    if (beginIndex > endIndex) {        throw new StringIndexOutOfBoundsException(endIndex - beginIndex);}    return ((beginIndex == 0) && (endIndex == count)) ? this :        new String(offset + beginIndex, endIndex - beginIndex, value);}

前面几行主要是做范围检查,最主要的是

new String(offset + beginIndex, endIndex - beginIndex, value);

String(int offset, int count, char value[]) {this.value = value;this.offset = offset;this.count = count;
}

可以看到JDK6里的substring复用了原来大String的整个value,即String里存放实际char的数组

/** The value is used for character storage. */private final char value[];

而只是通过修改beginIndex和offset来达到复用value,避免数组copy的麻烦(以及可以提高一点性能),但是问题就是,如果原 String很大,而substring保留的时间比较久,就有可能导致整个很大的value无法回收。JDK6下的修复方法就是,强制生成一个新的 String,避免复用原来String里的value,比如:

return this.largeString.substring(0,2) + "";//JDK6下的解决方法,不会出现out of memory

其实,这恰恰也是JDK8里面的实现方式。上src:

public String substring(int beginIndex, int endIndex) {        if (beginIndex < 0) {            throw new StringIndexOutOfBoundsException(beginIndex);}        if (endIndex > value.length) {            throw new StringIndexOutOfBoundsException(endIndex);}        int subLen = endIndex - beginIndex;        if (subLen < 0) {            throw new StringIndexOutOfBoundsException(subLen);}        return ((beginIndex == 0) && (endIndex == value.length)) ? this: new String(value, beginIndex, subLen);}

跟前面区别不大,再来看

public String(char value[], int offset, int count) {        if (offset < 0) {            throw new StringIndexOutOfBoundsException(offset);}        if (count < 0) {            throw new StringIndexOutOfBoundsException(count);}        // Note: offset or count might be near -1>>>1.if (offset > value.length - count) {            throw new StringIndexOutOfBoundsException(offset + count);}        this.value = Arrays.copyOfRange(value, offset, offset+count);}

可以看到,最后对value做了数组copy。

其实JDK8的修改也是褒贬不一,也有人认为JDK6里面的实现方法更好,效率更高,只要自己注意就可以避免问题的,这就是仁者见仁智者见智的问题了,只是需要知道,JDK6里String的这个小坑就好。

参考文章

  1. http://droidyue.com/blog/2014/12/14/substring-memory-issue-in-java/

  2. http://www.programcreek.com/2013/09/the-substring-method-in-jdk-6-and-jdk-7/


转载于:https://my.oschina.net/magicly007/blog/497227

相关文章:

第二弹,坐地铁就能学会的3种「非常有趣」的 Python 玩法

作者 | 黄伟呢来源 | 数据分析与统计学之美本文说明为什么要学习python&#xff1f;是因为不仅很多工作需要用到python&#xff0c;同时我们可以利用python做很多好玩儿的事儿。比如说下面的3种用法&#xff1a;1.利用python给小猪佩奇换背景色&#xff1b;2.利用python将小猪佩…

php比较长的configure

原先的字串./configure --prefix/usr/local/php --with-apxs2/usr/local/apache2/bin/apxs --enable-zip --enable-calendar --with-mysql/usr/local/mysql --with-pdo-mysql/usr/local/mysql --with-iconv/usr/local/libiconv --with-curl/usr/local/curl --with-gd/usr/local…

用mpvue实现的微信小程序版cnode社区

五一放假&#xff0c;没出去玩&#xff0c;想熟悉下vue的开发流程&#xff0c;又想体验下mpvue&#xff0c;于是写了个练手项目。一个用mpvue实现的cnode微信小程序版。 代码在仓库。欢迎各位star、fork、issue、pr。目前已经完成了百分之80的功能。个人感觉这个项目还是非常适…

PHP编译安装

#wget http://museum.php.net/php5/php-5.2.6.tar.gz &#xff08;下载php源码&#xff09; http://cn.php.net/releases/ 可以找到 #tar zxvf php-5.2.6.tar.gz #cd php-5.2.6 #./configure --prefix/usr/local/php --with-mysql/usr/local/mysql --with-apxs2/usr/local/apa…

Python 办公自动化,一键给PDF文件加密,超方便

作者 | 欣一来源 | Python爱好者集中营今天给大家做一个给PDF文件加密的GUI界面(图形用户界面)&#xff0c;方便现在的一些上班族白领们使用&#xff0c;尤其是需要给一些比较重要的PDF文件加密的时候&#xff0c;下面我们来看具体的步骤给PDF文件加密首先我们需要清楚的是如何…

YUM安装多个(多实例) Mysql

2019独角兽企业重金招聘Python工程师标准>>> 这里使用的是MYSQL的percona分支 先安装repo包 yum install percona-release-0.0-1.x86_64.rpm -y 想安装5.6的把5.5替换就行了,5.6的太耗内存了-。- yum install Percona-Server-server-55.x86_64 Percona-Server-clien…

scala可变长度参数函数

2019独角兽企业重金招聘Python工程师标准>>> scala可变长度参数函数只需要在参数列表的最后放一个星号&#xff0c;实验如下&#xff1a; def main (args:Array[String]){argsfun("Runoob", "Scala", "Python")} def argsfun(args:St…

3000 字推荐一个可视化神器,50 行 Python 代码制作数据大屏

作者 | 俊欣来源 | 关于数据分析与可视化今天小编给大家分享一个制作数据大屏的工具&#xff0c;非常的好用&#xff0c;100行左右的Python代码就可以制作出来一个完整的数据大屏&#xff0c;并且代码的逻辑非常容易理解。PywebIO介绍Python当中的PywebIO模块可以帮助开发者在不…

使用Varnish+ESI实现静态页面的局部缓存

页面静态化是搭建高性能网站必用的招式之一&#xff0c;页面静态化可以有效提升系统响应速度&#xff0c;同时也有利于搜索引擎优化。但在页面静态化后&#xff0c;静态页面之间包含&#xff08;例如所有的静态页面包含页头、页脚&#xff09;以及静态页面中的局部信息的动态更…

The Apply method of function object

2019独角兽企业重金招聘Python工程师标准>>> http://webreference.com As explained in the previous page, JavaScript 1.3 includes two new methods for the Function object, call() andapply(). The apply() method is a variation on the call() method. The …

资源 | 100+个自然语言处理数据集大放送,再不愁找不到数据!

奉上100多个按字母顺序排列的开源自然语言处理文本数据集列表&#xff08;原始未结构化的文本数据&#xff09;&#xff0c;快去按图索骥下载数据自己研究吧&#xff01; 数据集 Apache软件基金会公开邮件档案&#xff1a;截止到2011年7月11日全部公开可用的Apache软件基金会邮…

Java中ArrayList源码分析

一、简介 ArrayList是一个数组队列&#xff0c;相当于动态数组。每个ArrayList实例都有自己的容量&#xff0c;该容量至少和所存储数据的个数一样大小&#xff0c;在每次添加数据时&#xff0c;它会使用ensureCapacity()保证容量能容纳所有数据。 1.1、ArrayList 的继承与实现接…

介绍三种绘制时间线图的方法

作者 |周萝卜来源 |萝卜大杂烩今天我们再来分享几种不同的制作方法&#xff0c;大家可以自行比较下各种方法的优劣。Matplotlib 制作Matplotlib 作为 Python 家族最为重要的可视化工具&#xff0c;其基本的 API 以及绘制流程还是需要掌握的。尤其是该库的灵活程度以及作为众多工…

phpize是什么

安装php&#xff08;fastcgi模式&#xff09;的时候&#xff0c;常常有这样一句命令&#xff1a;/usr/local/webserver/php/bin/phpize 一、phpize是干嘛的&#xff1f; phpize是什么东西呢&#xff1f;php官方的说明&#xff1a; http://php.net/manual/en/install.pecl.phpiz…

C语言比较好的风格梳理

errno int err;tb malloc(sizeof(struct xtracer_table));if (!tb) {err errno;fprintf(stderr, "%s:%d, errno:%d, %s\n",__func__, __LINE__, err, strerror(err));return NULL;} 转载于:https://www.cnblogs.com/muahao/p/8979144.html

Linux下Memcache服务器端的安装

Linux下Memcache服务器端的安装服务器端主要是安装memcache服务器端&#xff0c;目前的最新版本是 memcached-1.3.0 。下载&#xff1a;http://www.danga.com/memcached/dist/memcached-1.2.2.tar.gz http://memcached.googlecode.com/files/memcached-1.4.9.tar.gz 另外&#…

如何用技术恢复模糊的图像?在线教学…

作者 |小白 来源 |小白学视觉 有人认为恢复模糊的图像是不可能的&#xff0c;因为会丢失信息。但我对这个问题进行了很多思考&#xff0c;并认为如果输出图像的大小与输入图像的大小相同&#xff0c;那实际上是可能的&#xff01;这样&#xff0c;输出就有足够的像素/信息来恢复…

数据库创建索引的原则

数据库建立索引的原则 铁律一&#xff1a;天下没有免费的午餐&#xff0c;使用索引是需要付出代价的 索引的优点有目共睹&#xff0c;但是&#xff0c;却很少有人关心过采用索引所需要付出的成本。若数据库管理员能够对索引所需要付出的代价有一个充分的认识&#xff0c;也就不…

Linux上实现ssh免密码登陆远程服务器

平常使用ssh登陆远程服务器时&#xff0c;都需要使用输入密码&#xff0c;希望可以实现通过密钥登陆而免除输入密码&#xff0c;从而可以为以后实现批量自动部署主机做好准备。 环境如下&#xff1a; IP地址操作系统服务器端10.0.0.10CentOS 6.5 x86客户端10.0.0.61CentOS 6.5 …

分享memcache和memcached安装过程

Memcache是什么&#xff1f; Memcache是一个自由和开放源代码、高性能、分配的内存对象缓存系统。用于加速动态web应用程序&#xff0c;减轻数据库负载。 它可以应对任意多个连接&#xff0c;使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间&#xff0c;然后建立一…

导入导出Android手机文件

1、获得root权限&#xff1a;adb root&#xff1b; 如提示adbd cannot run as root in production builds&#xff0c;参见我的另一篇文章&#xff1a;http://www.cnblogs.com/hdk1993/p/4770388.html 2、设置/system为可读写&#xff1a;adb remount&#xff1b; 3、将文件复制…

GPT-3 不够 Open,BigScience 构建开放语言模型,规模小 16 倍

编译 | 禾木木 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 大约一年前&#xff0c;总部位于纽约布鲁克林的自然语言处理初创公司 Hugging Face 推出了 BigScience。这是一个拥有 900 多名研究人员的国际项目&#xff0c;旨在更好地理解自然语言模型原理和提高大…

华为云微服务引擎CSE大量新特性上线,诚邀您免费体验

1、提供GO语言微服务开发框架SDK 支持插件化注册中心、多RPC协议&#xff08;已默认实现http和highway&#xff0c;可扩展&#xff09; 提供熔断降级、容错、路由管理、限流、错误注入、灰度发布等治理能力 2、提供Service Mesh商业版 支持.NET、Node.js、PHP等多语言应用…

memcache和memcached安装

首先要明确 memcache不是memcached第一步安装libevent #wget https://github.com/downloads/libevent/libevent/libevent-2.0.15-stable.tar.gz #tar libevent-2.0.15-stable.tar.gz #tar xzvf libevent-2.0.15-stable.tar.gz #cd libevent-2.0.15-stable #./configure --h…

点击按钮下载文件

RequestMapping("/download.do")public void download(HttpServletRequest request,HttpServletResponse response)throws Exception {String filePath "文件路径";FileInputStream fis null;OutputStream os null;try {fis new FileInputStream(fileP…

开源社区的危机:拒绝被“白嫖”?2大著名项目遭作者破坏

作者 | 林檎来源 | 数据实战派近日&#xff0c;一位开源开发者的故意破坏&#xff0c;再次引发了机构依赖开源库的争议。这一类开源库往往由维护者义务工作而支撑。被破坏的开源库是 Marak Squires 开发的 color.js 库和 faker.js 库。这两个库被广泛使用&#xff0c;其中不乏企…

状态和面向对象编程——1.定位步骤

定位 所有无人驾驶车要安全畅游全球&#xff0c;都必须经过一系列相同的步骤。 你一直在学习第一步&#xff1a;定位。在车辆能够安全驾驶之前&#xff0c;它们首先要使用传感器和收集的其他数据对它们所处的位置做出最佳估计。 卡尔曼滤波器 让我们来回顾一下卡尔曼滤波器对汽…

ldconfig命令详解,linux动态链接库

动态链接库管理命令 为了让动态链接库为系统所共享,还需运行动态链接库的管理命令--ldconfig.此执行程序存放在/sbin目录下. ldconfig命令的用途,主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如前介绍…

用于自动驾驶的实时 YUV 多任务 CNN

作者 | AI 修炼之路来源 | AI 修炼之路摘要本文提出了一种针对低功耗车用SoC优化的多任务卷积神经网络(CNN)结构。我们介绍了一个基于统一架构的网络&#xff0c;其中编码器由检测和分割两个任务共享。该网络以25FPS运行&#xff0c;分辨率为1280800。简要讨论了直接利用原生YU…

博客5:文件,目录以及用户的权限管理

linux用户与组的相关内容简介&#xff1a; 1.Linux用户&#xff1a;Username/UID管理员&#xff1a;root&#xff0c;0普通用户&#xff1a;1-65535系统用户&#xff1a;1-499&#xff08;在centos7上为1-999&#xff09;作用&#xff1a;对守护进程获取资源进行权限分配登录…