昨天看到一个blog,用一个极端例子来说明Java中的内存问题:
http://blog.xebia.com/2007/10/04/leaking-memory-in-java/
测试代码如下:
- public class TestGC {
- private String large = new String(new char[100000]);
-
- public String getSubString() {
- return this.large.substring(0,2);
- }
-
- public static void main(String[] args) {
- ArrayList<string></string> subStrings = new ArrayList<string></string>();
- for (int i = 0; i <1000000; i++) {
- TestGC testGC = new TestGC();
- subStrings.add(testGC.getSubString());
- }
- }
- }
-
如果要改掉这个bug,只要改写一下getSubString的方法就好了。
- public String getSubString() {
- return new String(this.large.substring(0,2));
- }
我测试了一下,确实如此。然后我看了一下JDK1.5.0_06代码中String类
from JDK1.5.0_06, String class:
- 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);
- }
这里用到的String的构造函数是private的
- private String(int offset, int count, char value[]) {
- this.value = value;
- this.offset = offset;
- this.count = count;
- }
上面那个例子程序改写的部分其实就是增加调用public的String构造函数另外创建一个String对象,我们再来看看这个public的构造函数,已经另外一个类似上面这个private的构造函数的public构造函数:
两个public的构造函数
- public String(String original) {
- int size = original.count;
- char[] originalValue = original.value;
- char[] v;
- if (originalValue.length > size) {
-
-
-
- v = new char[size];
- System.arraycopy(originalValue, original.offset, v, 0, size);
- } else {
-
-
- v = originalValue;
- }
- this.offset = 0;
- this.count = size;
- this.value = v;
- }
-
- public String(char value[], int offset, int count) {
- if (offset < 0) {
- throw new StringIndexOutOfBoundsException(offset);
- }
- if (count < 0) {
- throw new StringIndexOutOfBoundsException(count);
- }
-
- if (offset > value.length - count) {
- throw new StringIndexOutOfBoundsException(offset + count);
- }
- char[] v = new char[count];
- System.arraycopy(value, offset, v, 0, count);
- this.offset = 0;
- this.count = count;
- this.value = v;
- }
上面这两个public的构造函数,另外创建出来的String对象和原来的String对象并不共享其char数组的。而前面那个private的构造函数没有作arraycopy,是共享char其数组的。我想JDK这个实现有待商讨,内部使用的private的构造函数中不需要copy数组,可以共享数组。但private的构造函数被public的subString方法调用后,被外部使用时,就有问题了。
以后写相关代码时要小心了!
分享到:
- 2007-10-11 10:48
- 浏览 1453
- 评论(1)
- 论坛回复 / 浏览 (0 / 4401)
- 查看更多
相关推荐
Java中String和StringBuffer的区别实例详解 Java中String和StringBuffer都是用来存储字符串的对象,但是它们之间有着很大的区别。下面我们来详细介绍Java中String和StringBuffer的区别实例详解。 首先,String是不...
- **IBM的研究背景**:IBM的研究团队在过去十年中一直在诊断大型Java系统的内存和性能问题,并为此开发了一系列诊断工具,如Yeti等。他们与众多开源项目、大型商业应用及软件产品合作,涉及服务器端、客户端等多种...
这份名为"java_memory_tunning.zip_memory"的压缩包提供了一个关于Java内存调优的指南,主要聚焦于如何优化Java虚拟机(JVM)的内存配置以提升系统效率。以下是基于这个主题的详细知识点讲解: 1. **Java内存模型**...
Java中的字符串(String)是编程中不可或缺的部分,深入理解其内在机制对于提高代码性能至关重要。本文将探讨Java中字符串的内存管理,尤其是与Java虚拟机(JVM)内存模型的关联。 首先,Java内存模型分为堆内存...
"string-concatenate-outofmemory.rar_crash" 这个标题暗示了一个与字符串连接(concatenation)有关的问题,可能在特定条件下导致程序崩溃。描述中提到的测试目标是检查连续的字符串拼接是否会抛出异常,而不是直接...
在Java开发中,处理大型Excel文件时,可能会遇到内存溢出的问题。这通常是由于Java的默认内存设置不足以处理大量数据导致的。本解决方案主要针对使用Apache POI库进行Excel读取时遇到的这类问题。 首先,Apache POI...
在Java编程中,"java heap space"内存溢出是一个常见的问题,它通常发生在应用程序尝试分配超过JVM堆内存限制的对象时。这个问题对于任何Java开发者来说都至关重要,因为如果不妥善处理,可能会导致程序崩溃。以下是...
Java 22 (Oracle JDK 22) 在性能、稳定性和安全性方面进行了数千种改进,包括对Java语言、其API和性能,以及Java开发工具包(JDK)中工具的增强功能,以帮助开发人员提高工作效率。全新版本的 JDK 更新和改进了 12 ...
### Java中的日期处理类总结:Date、Calendar、GregorianCalendar、DateFormat、SimpleDateFormat 在Java编程中,日期时间处理是常见的需求之一。为了更好地理解和使用Java中的日期处理类,本篇文章将对Date、...
在Java编程中,获取计算机的硬件信息,如CPU使用率和内存使用情况,是一项常见的需求。这主要应用于系统监控、性能分析以及资源管理等方面。Java虽然不像C++或C#那样可以直接调用操作系统API,但它提供了Java ...
内存管理是计算机科学中的核心概念,特别是在编程语言如Java中,它对于程序的性能和稳定性至关重要。"Memory Management Simulator" 是一个模拟器,用于帮助理解并可视化内存管理的过程。这个模拟器利用了Java Swing...
此外,为了避免内存中的临时数据过多,还可以考虑使用Java的内存映射文件(Memory-Mapped File)。通过MappedByteBuffer,我们可以让操作系统负责数据的缓存和页面交换,这在处理大文件时能显著降低内存使用。 在...
在上面的题目中,选项 3"可以声明一个空类"是正确的,因为在 JAVA 中,可以声明一个不包含任何成员变量或方法的空类。 三、JAVA 注释方法 在 JAVA 中,注释方法可以分为三种:单行注释、多行注释和文档注释。单行...
在项目压缩包`CalculatorDemo.java`中,应包含上述所有逻辑的完整实现,以及可能的测试用例或示例代码,以确保所有功能的正确性。编写代码时,应遵循良好的编程实践,如注释、命名规范、代码复用等,以提高代码...
根据提供的文件信息,我们可以提取并总结出关于Java NIO(New Input/Output)的重要知识点。 ### Java NIO 概述 Java NIO 是 Java 平台的一个重要特性,首次出现在 Java 1.4 版本中。它为 Java 开发者提供了一套...
在Java编程中,获取CPU和内存信息是系统监控和性能分析的重要部分。下面将详细介绍如何使用Java来实现这一目标。 首先,我们从CPU信息开始。Java提供了`java.lang.management`包,该包中的`OperatingSystemMXBean`...
在Java编程语言中,将普通文本转换为Excel文件是一项常见的任务,特别是在数据分析、报表生成或者数据导出场景中。这个例子提供了一种方法,通过Java API来实现这一功能。主要涉及的技术点包括对Apache POI库的使用...
Java高速文件缓存是一种优化应用程序性能的技术,它通过将经常访问的数据存储在内存中,以减少对硬盘或网络I/O的依赖,从而显著提高数据读取速度。在Java中实现高效的文件缓存策略,可以利用Java集合框架、内存管理...
最后,深入理解泛型、继承和自动装箱拆箱,以及如何实现回调机制,这些都是Java编程中的高级主题。同时,掌握字节码层面的知识,可以让我们更深入地理解Java的运行机制。 通过以上学习,你将能够踏上Java工程师的成...
Java 9还包括了许多其他的小改进和API扩展,如`String`的`strip()`和`stripIndent()`方法,`OptionalInt`, `OptionalLong`和`OptionalDouble`的静态工厂方法,以及`ProcessHandle`的增强等。 以上只是Java 9开发...