面试题答案
一键面试分配方式
- 堆内存:由Java虚拟机自动管理分配。通过
new
关键字等方式创建对象时,对象会被分配到堆内存中。例如String str = new String("example");
,str
对象就分配在堆内存。 - 直接内存:不通过JVM堆,而是调用本地方法(如
Unsafe
类的方法)直接向操作系统申请内存。如ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
就是分配直接内存。
垃圾回收机制
- 堆内存:由JVM的垃圾回收器(如CMS、G1等)自动回收。当对象不再被引用,达到垃圾回收条件时,垃圾回收器会标记并清理这些对象占用的内存空间。
- 直接内存:不受JVM垃圾回收器直接管理。需要手动释放(如通过
Cleaner
机制),若不手动释放可能导致内存泄漏。例如在使用完直接内存的ByteBuffer
后,可通过sun.misc.Cleaner
来释放资源,但通常不建议直接使用,更好的方式是依赖对象生命周期结束时自动触发清理。
适用场景
- 堆内存:适用于创建和管理大量Java对象,日常的业务逻辑开发中创建的对象(如业务实体类、集合等)大多存储在堆内存。比如Web应用中的用户信息对象、订单对象等。
- 直接内存:适用于对I/O操作性能要求极高的场景,如NIO(New I/O)操作。在网络通信、文件读写等场景下,直接内存可以减少数据在堆内存和直接内存之间的拷贝,提高性能。例如在大数据量的文件传输时,使用直接内存的
ByteBuffer
进行数据读写。
性能优化方面选择直接内存的场景
在大数据量的I/O操作,如网络传输大量数据或读写大文件时,选择直接内存更优。例如,在实现一个高性能的文件传输系统时,若使用堆内存,数据需要先从磁盘读入堆内存,再从堆内存拷贝到直接内存用于网络发送,存在两次拷贝。而使用直接内存,数据可直接从磁盘读入直接内存,减少一次拷贝,提升传输性能。同时在需要频繁创建和销毁大量缓冲区对象时,直接内存可减少垃圾回收压力,因为直接内存不受JVM垃圾回收器直接管理,不会频繁触发垃圾回收影响应用性能。