专栏导航

JVM工作原理与实战

RabbitMQ入门指南

从零开始了解大数据


目录

专栏导航

前言

一、直接内存

1.直接内存作用

二、在直接内存上创建数据

总结


前言

JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了直接内存、在直接内存上创建数据等内容。


一、直接内存

在探讨直接内存之前,首先需要理解Java虚拟机(JVM)的运行时数据区。在《Java虚拟机规范》中,定义了几个关键的内存区域,如堆、方法区、程序计数器、Java虚拟机栈和本地方法栈。但直接内存,这一概念并不直接包含在《Java虚拟机规范》中。实际上,直接内存更多地是Java内存管理中的一个高级特性。

运行时数据区:

运行时数据区的详细讲解可以查看之前的文章:

JVM工作原理与实战(十五):运行时数据区-程序计数器-CSDN博客文章浏览阅读1.9k次,点赞52次,收藏35次。JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了运行时数据区、程序计数器等内容。 ​https://blog.csdn.net/jiangyq_/article/details/135578434JVM工作原理与实战(十六):运行时数据区-Java虚拟机栈-CSDN博客文章浏览阅读1.1k次,点赞24次,收藏23次。JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了运行时数据区、Java虚拟机栈等内容。 ​https://blog.csdn.net/jiangyq_/article/details/135587510JVM工作原理与实战(十七):运行时数据区-栈内存溢出-CSDN博客文章浏览阅读1.1k次,点赞37次,收藏13次。​JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了栈内存溢出、设置虚拟机栈的大小等内容。 ​https://blog.csdn.net/jiangyq_/article/details/135622580JVM工作原理与实战(十八):运行时数据区-堆-CSDN博客文章浏览阅读965次,点赞31次,收藏5次。​JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了运行时数据区、堆介绍、堆的关键参数等内容。https://blog.csdn.net/jiangyq_/article/details/135643531JVM工作原理与实战(十九):运行时数据区-方法区-CSDN博客文章浏览阅读535次,点赞12次,收藏10次。JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了方法区、方法区在Java虚拟机的实现、类的元信息、运行时常量池、字符串常量池、静态变量的存储等内容。https://blog.csdn.net/jiangyq_/article/details/135675559

1.直接内存作用

直接内存(Direct Memory)的引入与JDK 1.4中的新IO(NIO)机制紧密相关。NIO为Java提供了非阻塞的I/O操作,从而允许更高的并发性和更高效的I/O处理。而直接内存正是NIO实现的关键部分:

  • 解决对象回收问题:在Java中,当堆上的对象不再被引用时,这些对象将被标记为可回收。这个过程可能会影响正在运行的应用程序,因为垃圾回收器可能需要停止或阻塞应用程序线程以完成其工作。直接内存通过减少堆上的对象数量来减轻这种影响。通过将数据直接存储在直接内存中,应用程序可以持续运行,而不必担心垃圾回收器可能带来的暂停或阻塞。
  • 减少数据复制开销:传统的IO操作,如读取文件,通常涉及两个步骤:首先将数据从文件读入到缓冲区(通常是直接内存),然后再从缓冲区复制到Java堆上的对象。这种双重数据复制不仅增加了延迟,还增加了CPU和内存的使用。通过使用直接内存作为缓冲区,NIO可以直接在直接内存中处理数据,从而减少了数据从缓冲区到堆的复制过程,提高了IO操作的效率。

直接内存的出现不仅提高了Java应用程序的性能,而且也增加了应用程序对并发和大数据处理的适应能力。通过使用直接内存,应用程序可以更有效地管理其资源,同时提高其响应速度和吞吐量。

二、在直接内存上创建数据

Java NIO提供了一种机制,允许在直接内存上创建数据。要实现这一目标,可以使用ByteBuffer的allocateDirect方法,size参数表示希望分配的直接内存的大小,单位为字节。

ByteBuffer directBuffer = ByteBuffer.allocateDirect(size);

查看Java虚拟机的直接内存大小,可以使用arthas的memory命令,通过在命令行中输入memory来查看输出中的”direct”属性。

特殊情况下,可能需要手动调整直接内存的大小。可以通过设置JVM参数-XX:MaxDirectMemorySize来实现,这个参数允许开发者指定直接内存的最大大小。在设置-XX:MaxDirectMemorySize参数时,可以使用k或K表示千字节,m或M表示兆字节,g或G表示千兆字节,如果不设置这个参数,JVM会自动选择最大的分配大小。

案例:

public class Demo1 {public static int size = 1024 * 1024 * 100;public static List list = new ArrayList();public static int count = 0;public static void main(String[] args) throws IOException, InterruptedException {System.in.read();while (true) {ByteBuffer directBuffer = ByteBuffer.allocateDirect(size);list.add(directBuffer);System.out.println(++count);}}}

运行结果:

设置直接内存的大小:

-XX:MaxDirectMemorySize=1g

运行结果:


总结

JVM是Java程序的运行环境,负责字节码解释、内存管理、安全保障、多线程支持、性能监控和跨平台运行。本文主要介绍了直接内存、在直接内存上创建数据等内容,希望对大家有所帮助。