垃圾回收的悖论
所谓“成也萧何败萧何”。Java的垃圾回收确实带来了很多好处,为开发带来了便利。但是在一些高性能、高并发的情况下,垃圾回收确成为了制约Java应
用的瓶颈。目前JDK的垃圾回收算法,始终无法解决垃圾回收时的暂停问题,因为这个暂停严重影响了程序的相应时间,造成拥塞或堆积。这也是后续JDK增加
G1算法的一个重要原因。
当然,上面是从技术角度出发解决垃圾回收带来的问题,但是从系统设计方面我们就需要问一下了:
我们需要分配如此大的内存空间给应用吗?
我们是否能够通过有效使用内存而不是通过扩大内存的方式来设计我们的系统呢?
我们的内存中都放了什么
内存中需要放什么呢?个人认为,内存中需要放的是你的应用需要在不久的将来再次用到到的东西
。
想想看,如果你在将来不用这些东西,何必放内存呢?放文件、数据库不是更好?这些东西一般包括:
1. 系统运行时业务相关的数据。比如web应用中的session、即时消息的session等。这些数据一般在一个用户访问周期或者一个使用过程中都需要存在。
2. 缓存。缓存就比较多了,你所要快速访问的都可以放这里面。其实上面的业务数据也可以理解为一种缓存。
3. 线程。
因此,我们是不是可以这么认为,如果我们不把业务数据和缓存放在JVM中,或者把他们独立出来,那么Java应用使用时所需的内存将会大大减少,同时垃圾回收时间也会相应减少。
我认为这是可能的。
解决之道
数据库、文件系统
把所有数据都放入数据库或者文件系统,这是一种最为简单的方式。在这种方式下,Java应用的内存基本上等于处理一次峰值并发请求所需的内存。数据的获取都在每次请求时从数据库和文件系统中获取。也可以理解为,一次业务访问以后,所有对象都可以进行回收了。
这是一种内存使用最有效的方式,但是从应用角度来说,这种方式很低效。
内存-硬盘映射
上面的问题是因为我们使用了文件系统带来了低效。但是如果我们不是读写硬盘,而是写内存的话效率将会提高很多。
数据库和文件系统都是实实在在进行了持久化,但是当我们并不需要这样持久化的时候,我们可以做一些变通——把内存当硬盘使。
内存-硬盘映射很好很强大,既用了缓存又对Java应用的内存使用又没有影响。Java应用还是Java应用,他只知道读写的还是文件,但是实际上是内存。
这种方式兼得的Java应用与缓存两方面的好处。memcached的广泛使用也正是这一类的代表。
同一机器部署多个JVM
这也是一种很好的方式,可以分为纵拆和横拆。纵拆可以理解为把Java应用划分为不同模块,各个模块使用一个独立的Java进程。而横拆则是同样功能的应用部署多个JVM。
通过部署多个JVM,可以把每个JVM的内存控制一个垃圾回收可以忍受的范围内即可。但是这相当于进行了分布式的处理,其额外带来的复杂性也是需要评估的。另外,也有支持分布式的这种JVM可以考虑,不要要钱哦:)
程序控制的对象生命周期
这种方式是理想当中的方式,目前的虚拟机还没有,纯属假设。即:考虑由编程方式配置哪些对象在垃圾收集过程中可以直接跳过,减少垃圾回收线程遍历标记的时间。
这种方式相当于在编程的时候告诉虚拟机某些对象你可以在*时间后在进行收集或者由代码标识可以收集了(类似C、C++),在这之前你即便去遍历他也是没有效果的,他肯定是还在被引用的。
这种方式如果JVM可以实现,个人认为将是一个飞跃,Java即有了垃圾回收的优势,又有了C、C++对内存的可控性。
线程分配
Java的阻塞式的线程模型基本上可以抛弃了,目前成熟的NIO框架也比较多了。阻塞式IO带来的问题是线程数量的线性增长,而NIO则可以转换成为常数
线程。因此,对于服务端的应用而言,NIO还是唯一选择。不过,JDK7中为我们带来的AIO是否能让人眼前一亮呢?我们拭目以待。
其他的JDK
本文说的都是Sun的JDK,目前常见的JDK还有JRocket和IBM的JDK。其中JRocket在IO方面比Sun的高很多,不过Sun
JDK6.0以后提高也很大。而且JRocket在垃圾回收方面,也具有优势,其可设置垃圾回收的最大暂停时间也是很吸引人的。不过,系统Sun的G1实
现以后,在这方面会有一个质的飞跃。
参考资料
能整理出上面一些东西,也是因为站在巨人的肩上。下面是一些参考资料,供大家学习,大家有更好的,可以继续完善:)
· Java 理论与实践: 垃圾收集简史
· Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning
· Improving Java Application Performance and Scalability by Reducing Garbage Collection Times and Sizing Memory Using JDK 1.4.1
· Hotspot memory management whitepaper
· Java Tuning White Paper
· Diagnosing a Garbage Collection problem
· Java HotSpot VM Options
· A Collection of JVM Options
· Garbage-First Garbage Collection
· Frequently Asked Questions about Garbage Collection in the HotspotTM JavaTM Virtual Machine
· JProfiler试用手记
· Java6 JVM参数选项大全
· 《深入Java虚拟机》。虽然过去了很多年,但这本书依旧是经典。
这里是本系列的最后一篇了,很高兴大家能够喜欢这系列的文章。期间也提了很多问题,其中有些是我之前没有想到的或者考虑欠妥的,感谢提出这些问题的朋友,我也学到的不少东西。
相关推荐
JVM内存管理主要关注对象的生命周期和内存分配,了解这些有助于确定合适的内存大小和垃圾回收策略。 2. **垃圾回收算法** 基本的垃圾回收算法有标记-清除、复制、标记-整理和分代收集等。每种算法都有其优缺点,...
2. **内存管理与垃圾回收**:Java的内存管理是通过垃圾回收机制自动完成的,考生需要了解如何创建对象,对象生命周期,以及如何避免内存泄漏。 3. **集合框架**:Java集合框架包括List、Set、Map接口及其实现类,如...
- **GC机制与原理**:深入理解垃圾回收机制的工作原理,包括不同类型的GC(年轻代GC、老年代GC)触发条件。 - **ClassLoader**:讲解JVM中的类加载机制,包括自定义类加载器的实现。 - **双亲委派模型**:解释双亲...
4. **内存管理与垃圾回收**:理解Java的自动内存管理机制,包括对象的生命周期、引用类型以及垃圾回收的基本原理。 5. **字符串与字符流**:掌握String类的特性和常用方法,以及字符流I/O(如Reader和Writer)的...
此外,为了更好地准备面试,求职者还应熟悉一些常见的面试题目,例如“解释Java中的垃圾回收机制”、“比较Java中的ArrayList和LinkedList”、“解释什么是RESTful API”等。通过反复练习这些问题,并且熟悉回答的...
10. **垃圾收集与内存管理**:理解Java的自动内存管理和垃圾回收机制,可以避免内存泄漏和性能问题。 通过学习《Java编程思想》中的源代码和课后练习,你可以深入理解这些知识点,并通过实际操作提升编程技能。在...
例如,面试者可能会被问到关于垃圾回收机制、内存模型、锁的实现原理,以及如何解决高并发场景下的性能问题。 2. **C++基础与进阶**:C++面试中,面试官可能考察C++的语法特性、STL使用、模板元编程、内存管理、...
熟悉JVM的工作原理有助于优化程序性能,例如垃圾回收、内存管理等。 另外,可以关注开源库,如Apache Commons的Java Collections框架,这些库提供了丰富的数据结构和算法实现,通过学习它们的源代码,能深化对Java...