在《Java程序性能优化》3.12小节用一个例子说明在Java 6之前的版本(Java 7中已经解决)使用subString方法可能会带来性能的问题,但是并没有说明为什么会出现性能问题,我从JVM内存模型层面试着分析这个问题。
源代码:
public class Test { public static void main(String[] args) { List<String> handler = new ArrayList<String>(); for (int i = 0; i < 1000; i++) { HugeStr h = new HugeStr(); // Line 1 //ImprovedHugeStr h = new ImprovedHugeStr(); // Line 2 handler.add(h.getSubString(1, 5)); // Line 3 } } static class HugeStr { private String str = new String(new char[100000]); public String getSubString(int begin, int end) { return str.substring(begin, end); } } static class ImprovedHugeStr { private String str = new String(new char[100000]); public String getSubString(int begin, int end) { return new String(str.substring(begin, end)); } } }
这是HugeStr一次for循环的简易内存分配示意图。
说明:
Line 1这一行实际上做了两个操作,在堆中创建了一个新的HugeStr对象,并将h指向堆中新创建的HugeStr对象;而HugeStr对象中又包含一个str属性,同理,此刻str将指向内存中另外String对象,该String对象包含一个value属性指向一个100000长度的数组。
Line 3这一行关注h.getSubString()这个操作,在Java 7以前,这里会新new一个字符串,并将原字符串的value的引用传递给新的字符串,如说上3.12第三幅图展示的样子,这样新的字符串的value属性则指向了Line 1上那个长度很长的字符串。
当循环结束后,h的引用变成无效引用,那么其他相关联的无效引用如图中红色X所示。但是100000长度的数组则不能被确定为无效引用,因为ArrayList.add()方法执行之后,会将Line 3生成的对象放置在该集合中。
对比ImprovedHugeStr
说明:ImprovedHugeStr与HugeStr唯一的区别在于在getSubstring()方法的时候新new了一个字符串,而正好是这个new操作,Java将会将原来value的数组复制并生成新的数组,也就使得大数组的引用在经过循环之后变成了无效引用,当垃圾回收器需要进行gc的时候会将其回收。上JDK源码。
public String(String original) { int size = original.count; char[] originalValue = original.value; char[] v; if (originalValue.length > size) { // The array representing the String is bigger than the new // String itself. Perhaps this constructor is being called // in order to trim the baggage, so make a copy of the array. int off = original.offset; v = Arrays.copyOfRange(originalValue, off, off+size); } else { // The array representing the String is the same // size as the String, so no point in making a copy. v = originalValue; } this.offset = 0; this.count = size; this.value = v; }
相关推荐
- **解决Java程序响应慢的问题**: 当遇到Java程序响应变慢的情况时,可以通过分析CPU使用率、内存消耗情况等指标来定位问题。使用`jstack`工具可以获取线程堆栈信息,从而找出阻塞线程;使用`jmap`可以获得内存快照...
- **Java内存管理**:研究Java的垃圾收集机制,了解内存泄漏和性能优化。 4. **Web开发** - **Servlet与JSP**:学习如何使用Servlet处理HTTP请求,以及JSP技术进行动态网页开发。 - **MVC框架**:了解Spring MVC...
`String#substring()`方法现在返回一个原始字符串的视图,而不是创建一个新的字符串对象,这减少了内存分配,提高了性能。 4. **并行流API扩展**: 并行流在Java 8中引入,Java 11对其进行了扩展,添加了`...
17. **性能优化**:学习如何分析和优化Java应用程序的性能,包括JVM参数调整、内存管理和代码优化技巧。 通过这些教程,你将能够全面掌握Java SE编程的基本技能,并具备解决实际问题的能力。由于Java是一种广泛应用...
Java的垃圾回收机制自动管理内存,但理解内存模型、对象生命周期、引用类型(强引用、软引用、弱引用、虚引用)以及如何避免内存泄漏是优化程序性能的重要环节。 十、Java标准库 熟悉Java标准库中的各种类和接口,...
14. **性能优化**:分析和解决Java程序的性能问题,如内存泄漏、CPU占用过高、GC调优等。 15. **并发编程**:深入理解并发编程的相关概念,如并发容器、线程池、并发工具类等。 16. **Spring框架**:学习使用...
- 了解不同数据结构的特点和适用场景对于优化程序性能至关重要。 **2.2 算法及性能分析** - **2.2.1 算法** - 算法是一系列解决问题的步骤,是程序的核心。 - 良好的算法设计可以提高程序的效率和可读性。 - *...
在Java编程中,性能优化是一项至关重要的任务,它涉及到代码的效率、内存管理和资源消耗等方面。本文将深入探讨如何在Java中实现字符串(String)对象的性能优化,这是Java开发中最常用的类型之一,其优化能够显著...
此外,`substring()`和`length()`等方法也进行了性能优化。 5. **NIO.2**:Java 7引入了新的非阻塞I/O API,称为New I/O 2,位于`java.nio.file`包下。`Files`类提供了许多文件操作的静态方法,如创建、删除、复制...
在Java编程语言中,创建一个包含0到10MB数据的字符串通常涉及到字符串的动态构建和内存管理。这里我们将深入探讨如何使用`StringBuilder`类来高效地...在编写程序时,理解这些基础工具的使用对于优化代码性能至关重要。
- **性能优化**:随着JIT编译器的发展,Java的性能得到了显著提升。 ##### 3、什么是跨平台性?原理是什么?JVM 跨平台性是指编写在一种平台上(如Windows)的程序可以在其他平台上(如Linux或Mac OS)运行而无需...
JDK 6对这些类型进行了优化,使得程序性能有所提升。 3. 控制结构:包括条件语句(if、switch)、循环(for、while)和跳转语句(break、continue),是编写复杂逻辑的核心部分。 二、异常处理 Java的异常处理机制...
- **内存区域**: 理解堆、栈、方法区、程序计数器、本地方法栈等内存区域。 7. **多线程** - **线程的创建与状态**: 实现Runnable接口或继承Thread类,理解线程的生命周期。 - **同步机制**: synchronized关键字...
- **编译与运行**:熟悉如何使用命令行工具编译和运行Java程序。 - **控制台输出**:学习如何使用`System.out.println`进行文本输出。 #### 2. 如何构建自己的Java库? - **项目结构**:创建一个清晰的目录结构来...
5. **性能优化:** 对于性能敏感的应用,应当关注算法的选择和数据结构的使用,例如使用`HashSet`和`HashMap`代替`ArrayList`进行查找操作可以极大地提升性能。 通过遵循这些最佳实践,开发者可以在编写Java程序时...
21. **性能优化**:学习如何分析和优化Java程序的性能,包括垃圾回收、内存泄漏和代码优化技巧。 "day13"文件可能包含第13天学习的具体代码示例和练习,涵盖上述知识点的一个或多个部分。通过详细阅读和实践这些...
Java 8之后引入了红黑树来优化链表性能。 17. **序列化和反序列化** - 序列化是将对象的状态转化为字节流的过程,便于存储或在网络中传输。 - 反序列化则是将字节流恢复成对象的过程。 - 常见的序列化方式有Java...
- 理解垃圾回收机制对于优化应用程序性能至关重要。 **5. switch 语句支持的数据类型** - **背景:** Java 中的 switch 语句允许对不同的值执行不同的代码块。 - **知识点:** - Java 7 开始支持 byte、short、...
12. **JVM**:了解Java虚拟机的工作原理,包括类加载机制、内存模型(堆、栈、方法区、本地方法栈等)、垃圾回收机制,有助于优化程序性能和避免内存泄漏。 13. **Java SE和Java EE**:Java标准版(SE)是Java的...
理解其工作原理,以及如何避免内存泄漏,对优化程序性能至关重要。 最后,文件和I/O流是Java操作文件和数据交换的基础。学习如何读写文件,使用InputStream和OutputStream家族,以及更高级的BufferedReader和...