×

java虚拟机规范 java虚拟机 java虚拟机内存模型

java虚拟机规范(java虚拟机内存模型)

admin admin 发表于2023-03-24 02:55:31 浏览42 评论0

抢沙发发表评论

本文目录

java虚拟机内存模型

Java虚拟机相当于一个抽象的计算机操作系统,其管理的内存区域大体上可以分为栈和堆,就像c或c++中对内存的分类一样,但这样的分类对于Java虚拟机来说太过粗浅,实际上Java虚拟机管理的内存区域分为程序计数器、虚拟机栈、本地方法栈、堆和方法区,根据各区域是属于线程私有还是由线程共享,这些区域可以分为两类,下面分别进行说明。

Java为什么不能实现真正泛型

一句话回答:Java一言九鼎!

Java在发布之初,就将二进制兼容这个承诺写入了《Java虚拟机规范》中,为了兼容Java1.5之前的版本最终选择了此方案。

虽然兼容的方案不止是擦除这一条路,但是这个承诺确实是导致其没有采用类似C#那种真泛型的方案的最重要的原因。

如何准确理解Java中的堆与栈

一种是栈内存,一种是堆内存。堆是用来存放对象的,栈是用来运行程序的。

堆需要通过new等方式来创建;栈内存的主要作用是存放基本数据类型和引用变量。栈的内存管理是通过栈的“后进先出“模式来实现的。

栈作为一种数据结构,是一种只能在一端进行开始插入和删除操作的特殊的线性表。它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后进入的数据在栈顶,需要读取数据的时候从栈顶开始弹出数据(最后一个进入的数据被第一个读出来)。

怎样才能更好地学习JAVA有快又好

首先,一入java深似海。若未入,建议考虑其他语言,语言本身没有哪个是最好的。若执意要入,你面对的将是一片海洋。多快好省的系统化的学习Java,目前我想不到很好的途径。

如果是踏踏实实一步步来,我倒是有一些建议。你需要打好java基础,重要的事情不说二遍。IO,JDBC,集合,反射,多线程,socket等等,最主要的是培养面向对象的编程思想,这是java的灵魂,封装继承多态。基础打好了,jdk一些经典算法和设计模式的实现方式建议了解,培养看源码的能力,算法能力,架构设计能力。之后,强烈推荐了解虚拟机规范,懂类加载机制,熟悉java内存模型,这也是很多培训机构速成程序员的弱项。接下来你就可以昂首挺胸的进入J2EE的世界了,也是现在大多数程序员在搞的东西。J2EE进入可以提前,毕竟前面的东西都是持续学习的过程。这时候你开始了解JSP,servlet。在接触各种框架之前,强烈建议,深入了解TCP/IP协议,

如何正确学会Java虚拟机调优

一点小经验仅供参考:

1) 堆

运行时数据区域,所有类实例和数组的内存均从此处分配。Java 虚拟机启动时创建。对象的堆内存由称为垃圾回收器 的自动内存管理系统回收。

堆由两部分组成:

其中eden+fromspace+tospace也叫年轻代(young),old space叫旧生代.

其中还有S1,S0(在JDK的自带工具输出中会看到),分别指的是Survivor space,存放每次垃圾回收后存活的对象.

Old Generation , 主要存放应用程序中生命周期长的存活对象

垃圾回收主要是对Young Generation块和Old Generation块内存进行回收,YG用来放新产生的对象,经过几次回收还没回收掉的对象往OG中移动,

对YG进行垃圾回收又叫做MinorGC,对OG垃圾回收叫MajorGC,两块内存回收互不干涉

2) 非堆内存

JVM具有一个由所有线程共享的方法区。方法区属于非堆内存。它存储每个类结构,如运行时常数池、字段和方法数据,以及方法和构造方法的代码。它是在 Java 虚拟机启动时创建的。

除了方法区外,Java 虚拟机实现可能需要用于内部处理或优化的内存,这种内存也是非堆内存。 例如,JIT 编译器需要内存来存储从 Java 虚拟机代码转换而来的本机代码,从而获得高性能。

Permanent Generation (图中的Permanent Space) 存放JVM自己的反射对象,比如类对象和方法对象

3) 回收算法和过程

JVM采用一种分代回收 (generational collection) 的策略,用较高的频率对年轻的对象(young generation)进行扫描和回收,这种叫做minor collection,而对老对象(old generation)的检查回收频率要低很多,称为major collection。这样就不需要每次GC都将内存中所有对象都检查一遍。

当一个URL被访问时,内存申请过程 如下:

A. JVM会试图为相关Java对象在Eden中初始化一块内存区域

B. 当Eden空间足够时,内存申请结束。否则到下一步

C. JVM试图释放在Eden中所有不活跃的对象(这属于1或更高级的垃圾回收), 释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区

D. Survivor区被用来作为Eden及OLD的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区

E. 当OLD区空间不够时,JVM会在OLD区进行完全的垃圾收集(0级)

F. 完全垃圾收集后,若Survivor及OLD区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现”out of memory错误”

对象衰老的过程

young generation的内存,由一块Eden(伊甸园,有意思)和两块Survivor Space(1.4文档中称为semi-space)构成。新创建的对象的内存都分配自eden。两块Survivor Space总有会一块是空闲的,用作copying collection的目标空间。Minor collection的过程就是将eden和在用survivor space中的活对象copy到空闲survivor space中。所谓survivor,也就是大部分对象在伊甸园出生后,根本活不过一次GC。对象在young generation里经历了一定次数的minor collection后,年纪大了,就会被移到old generation中,称为tenuring。(是否仅当survivor space不足的时候才会将老对象tenuring? 目前资料中没有找到描述)

剩余内存空间不足会触发GC,如eden空间不够了就要进行minor collection,old generation空间不够要进行major collection,permanent generation空间不足会引发full GC。

4 接下来这部分讲解的是TOMCAT或者其他服务器出现如下错误时的分析:

1、首先是:java.lang.OutOfMemoryError: Java heap space

解释:

Heap size 设置

JVM堆的设置是指java程序运行过程中JVM可以调配使用的内存空间的设置.JVM在启动的时候会自动设置Heap size的值,其初始空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置。Heap size 的大小是Young Generation 和Tenured Generaion 之和。

提示:在JVM中如果98%的时间是用于GC且可用的Heap size 不足2%的时候将抛出此异常信息。

提示:Heap Size 最大不要超过可用物理内存的80%,一般的要将-Xms和-Xmx选项设置为相同,而-Xmn为1/4的-Xmx值。

解决方法:

手动设置Heap size

修改TOMCAT_HOME/bin/catalina.bat,在“echo “Using CATALINA_BASE: $CATALINA_BASE“”上面加入以下行:

Java代码

set JAVA_OPTS=%JAVA_OPTS% -server -Xms800m -Xmx800m -XX:MaxNewSize=256m

set JAVA_OPTS=%JAVA_OPTS% -server -Xms800m -Xmx800m -XX:MaxNewSize=256m

或修改catalina.sh

在“echo “Using CATALINA_BASE: $CATALINA_BASE“”上面加入以下行:

JAVA_OPTS=“$JAVA_OPTS -server -Xms800m -Xmx800m -XX:MaxNewSize=256m“

2、其次是:java.lang.OutOfMemoryError: PermGen space

原因:

PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中,它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的应用中有很CLASS的话,就很可能出现PermGen space错误,这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了。

解决方法:

1. 手动设置MaxPermSize大小

修改TOMCAT_HOME/bin/catalina.bat(Linux下为catalina.sh),在Java代码

“echo “Using CATALINA_BASE: $CATALINA_BASE“”上面加入以下行:

set JAVA_OPTS=%JAVA_OPTS% -server -XX:PermSize=128M -XX:MaxPermSize=512m

“echo “Using CATALINA_BASE: $CATALINA_BASE“”上面加入以下行:

set JAVA_OPTS=%JAVA_OPTS% -server -XX:PermSize=128M -XX:MaxPermSize=512m

catalina.sh下为:

Java代码

JAVA_OPTS=“$JAVA_OPTS -server -XX:PermSize=128M -XX:MaxPermSize=512m“

JAVA_OPTS=“$JAVA_OPTS -server -XX:PermSize=128M -XX:MaxPermSize=512m“

JVM的默认设置

堆 (heap)(News Generation 和Old Generaion 之和)的设置

初始分配的内存由-Xms指定,默认是物理内存的1/64但小于1G。

最大分配的内存由-Xmx指定,默认是物理内存的1/4但小于1G。

默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制,可以由-XX:MinHeapFreeRatio=指定。

默认空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制,可以由-XX:MaxHeapFreeRatio=指定。

服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小,所以上面的两个参数没啥用。

-Xmn 设置young generation的heap大小

-XX:MinHeapFreeRatio与-XX:MaxHeapFreeRatio设定空闲内存占总内存的比例范围,这两个参数会影响GC的频率和单次GC的耗时。-XX:NewRatio决定young与old generation的比例。Young generation空间越大,minor collection频率越低,但是old generation空间小了,又可能导致major collection频率增加。-XX:NewSize和-XX:MaxNewSize直接指定了young generation的缺省大小和最大大小。

非堆内存 的设置

默认分配为64M

-XX:PermSize设置最小分配空间,-XX:MaxPermSize设置最大分配空间。一般把这两个数值设为相同,以减少申请内存空间的时间。

再讲解和笔记下,JDK下的一些相关看内存管理工具的使用:

查看jvm内存状态:

jstat -gcutil pid 1000 20

异常情况的例子

jstat -gcutil pid 1000 20

S0 S1 E O P YGC YGCT FGC FGCT GCT

0.00 0.00 99.99 82.51 53.11 2409 1.205 10117 7250.393 7251.598

0.00 0.00 83.42 82.55 53.10 2409 1.205 10118 7252.650 7253.855

0.00 0.00 56.06 82.46 53.10 2410 1.205 10120 7254.467 7255.672

0.00 0.00 32.11 82.55 53.10 2411 1.205 10121 7256.673 7257.877

0.00 0.00 99.99 82.55 53.10 2412 1.205 10123 7257.026 7258.231

0.00 0.00 76.00 82.50 53.10 2412 1.205 10124 7259.241 7260.446

这个数据显示Full GC频繁发生。

正常情况的例子

S0 S1 E O P YGC YGCT FGC FGCT GCT

0.00 0.00 0.24 55.39 99.60 171 0.667 1339 393.364 394.031

0.00 0.00 0.24 55.39 99.60 171 0.667 1339 393.364 394.031

0.00 0.00 0.24 55.39 99.60 171 0.667 1339 393.364 394.031

0.00 0.00 0.24 55.39 99.60 171 0.667 1339 393.364 394.031

0.00 0.00 0.24 55.39 99.60 171 0.667 1339 393.364 394.031

0.00 0.00 0.24 55.39 99.60 171 0.667 1339 393.364 394.031

参数含义:

S0:Heap上的 Survivor space 0 段已使用空间的百分比

S1:Heap上的 Survivor space 1 段已使用空间的百分比

E: Heap上的 Eden space 段已使用空间的百分比

O: Heap上的 Old space 段已使用空间的百分比

P: Perm space 已使用空间的百分比

YGC:从程序启动到采样时发生Young GC的次数

YGCT:Young GC所用的时间(单位秒)

FGC:从程序启动到采样时发生Full GC的次数

FGCT:Full GC所用的时间(单位秒)

GCT:用于垃圾回收的总时间(单位秒)

2 Dump出内存

2.1 找出要dump的线程pid

在Linux下,使用ps –aux

2.2 Dump出内存使用详情

可以通过命令:

jmap -dump:file=a.hprof pid

例如:jmap -heap 2343,可以看到

Attaching to process ID 2343, please wait...

Debugger attached successfully.

Server compiler detected.

JVM version is 11.0-b16

using thread-local object allocation.

Parallel GC with 8 thread(s)

Heap Configuration:

MinHeapFreeRatio = 40

MaxHeapFreeRatio = 70

MaxHeapSize = 4294967296 (4096.0MB)

NewSize = 2686976 (2.5625MB)

MaxNewSize = -65536 (-0.0625MB)

OldSize = 5439488 (5.1875MB)

NewRatio = 2 (YG,OG 大小比为1:2)

SurvivorRatio = 8

PermSize = 21757952 (20.75MB)

MaxPermSize = 268435456 (256.0MB)

Heap Usage:

PS Young Generation

Eden Space:

capacity = 1260060672 (1201.6875MB)

used = 64868288 (61.86322021484375MB)

free = 1195192384 (1139.8242797851562MB)

5.148028935546367% used

From Space:

capacity = 85524480 (81.5625MB)

used = 59457648 (56.70323181152344MB)

free = 26066832 (24.859268188476562MB)

69.52120375359195% used

To Space:

capacity = 85852160 (81.875MB)

used = 0 (0.0MB)

free = 85852160 (81.875MB)

0.0% used

~~~~~~~~~~~~~~~~~~~~~~~~~~这三块为上面所说的YG大小和使用情况

PS Old Generation

capacity = 2291138560 (2185.0MB)

used = 1747845928 (1666.8757705688477MB)

free = 543292632 (518.1242294311523MB)

76.28722062099989% used

~~~~~~~~~~~~~~~~~~~~~~~~~~OG大小和使用情况

PS Perm Generation

capacity = 108265472 (103.25MB)

used = 107650712 (102.6637191772461MB)

free = 614760 (0.5862808227539062MB)

99.43217353728436% used

jstat

jstat是vm的状态监控工具,监控的内容有类加载、运行时编译及GC。

使用时,需加上查看进程的进程id,和所选参数。以下详细介绍各个参数的意义。

jstat -class pid:显示加载class的数量,及所占空间等信息。

jstat -compiler pid:显示VM实时编译的数量等信息。

jstat -gc pid:可以显示gc的信息,查看gc的次数,及时间。其中最后五项,分别是young gc的次数,young gc的时间,full gc的次数,full gc的时间,gc的总时间。

jstat -gccapacity:可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小,如:PGCMN显示的是最小perm的内存使用量,PGCMX显示的是perm的内存最大使用量,PGC是当前新生成的perm内存占用量,PC是但前perm内存占用量。其他的可以根据这个类推, OC是old内纯的占用量。

jstat -gcnew pid:new对象的信息。

jstat -gcnewcapacity pid:new对象的信息及其占用量。

jstat -gcold pid:old对象的信息。

jstat -gcoldcapacity pid:old对象的信息及其占用量。

jstat -gcpermcapacity pid: perm对象的信息及其占用量。

jstat -util pid:统计gc信息统计。

jstat -printcompilation pid:当前VM执行的信息。

除了以上一个参数外,还可以同时加上 两个数字,如:jstat -printcompilation 3024 250 6是每250毫秒打印一次,一共打印6次,还可以加上-h3每三行显示一下标题。

例子:

jstat -gcutil pid 1000 20

S0 S1 E O P YGC YGCT FGC FGCT GCT

47.49 0.00 64.82 46.08 47.69 20822 2058.631 68 22.734 2081.365

0.00 37.91 38.57 46.13 47.69 20823 2058.691 68 22.734 2081.425 这里发生了一次YG GC,也就是MinorGC,耗时0.06s

46.69 0.00 15.19 46.18 47.69 20824 2058.776 68 22.734 2081.510

46.69 0.00 74.59 46.18 47.69 20824 2058.776 68 22.734 2081.510

0.00 40.29 19.95 46.24 47.69 20825 2058.848 68 22.734 2081.582

MajorGC平均时间:22.734/68=0.334秒

MinorGC平均时间:2058.691/20823=0.099秒


Java JVM怎么学习啊从哪方面入手

可以先从类加载开始,了解JVM的类加载原理,类加载过程,然后熟悉类加载器和类加载机制,其次可以去了解Java内存结构(运行时数据区),重点了解堆栈两块区域,了解堆的分代模型,GC的垃圾算法,垃圾收集器,以及常见的JVM参数设置,最后结合企业的业务场景来监测和调试JVM参数,做一次JVM实践调优,这样子的学习路线我认为是可以快速上手掌握JVM的

-------微信搜索:【猿灯塔】 微信公众号 干货技术文章 以及技术文档,大厂面试题 助你成就架构师之路

JAVA的内存是如何划分的

谢邀~

关于JVM的知识,一直令很多Java程序员头疼,不过JVM也是值得我们深入学习的内容,下面我就谈谈自己对JVM内存划分的理解。

什么是Java的内存

学习Java的朋友应该都知道,Java程序是在JVM上运行的,所以我们一般谈的Java内存划分事实上都是指的JVM内存区域的划分。在讨论JVM内存划分之前,我们需要知道Java程序的执行过程(手动画图,有点儿丑):

通过这个图可以看到,JVM在执行Java程序的时候,要用到一块空间来存储运行期间用到的数据,这块区域就是我们经常用的运行时区域,也就是常说的JVM内存。

Java的内存的组成

程序计数器(Program Counter Register)、Java栈(VM Stack)、本地方法栈(Native Method Stack)、方法区(Method Area)、堆(Heap)。

这个是Java虚拟机规范规定好的,但是具体怎么实现还是由厂商决定的。

运行的时候,每一个区域存的是什么数据的,先看一张图:

  • 程序计数器

保存指令地址,也就是存的是下一条执行所在的存储地址。如果是多线程的时候,因为一个CPU在一个时刻只能执行一条命令,为了能够让每一个线程在切换之后能够恢复切换之前的位置,每个线程就需要有自己的计数器,所以说:程序计数器是每个线程私有的。

  • 虚拟机栈

就是Stack,存放的是一个个的栈帧,每个栈帧对应一个被调用的方法。在栈帧中存着局部变量表、操作数栈、指向当前方法所属的类的运行时常量池的引用、方法返回地址和一些额外的附加信息。(这几个东西都是干啥的,可以单独写篇文章说了...)

每个线程都会有一个自己的Java栈,也是线程私有的。

  • 本地方法栈

本地方法栈与Java栈的作用和原理非常相似。区别只不过是Java栈是为执行Java方法服务的,而本地方法栈则是为执行本地方法(Native Method)服务的。

在HotSopt虚拟机中直接就把本地方法栈和Java栈合二为一。


存储对象本身的以及数组,堆是被所有线程共享的,在JVM中只有一个堆。

  • 方法区

存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等,也是被线程共享的。

Java内存区域划分,是一个中高级程序员的必修课,希望我的回答能够帮助到你!

我将持续分享Java开发、架构设计、程序员职业发展等方面的见解,希望能得到你的关注。

Java是如何实现平台无关性的

所谓平台无关性指的就是程序可以在任何平台运行,而不需要改动程序本身。基于这个概念,java平台无关性实现主要由一下几个部分组成。

1、中间字节码文件

我们都知道java程序中的代码文件最终都会被编译成字节码文件,即. class文件。这个编译工作可以通过javac命令来完成。平常开发中我们更多的是通过开发工具来完成的。假如我们用maven构建一个项目,我们可以在idea中直接 build jar或者build war。最终生成的文件就是字节码文件。这些字节码文件是不能被操作系统识别的,操作系统只能识别0和1。那这些文件靠谁识别呢?JVM。

2、JVM

java虚拟机即jvm,是运行在操作系统之上的一个虚拟的编译系统。它的作用就是将字节码文件翻译成操作系统可以识别的语言0和1。这就是我们为什么学java,先要安装jdk。jdk中包括了jvm。没有jvm,java源代码是无法编译成字节码文件的。不同操作系统我们需要安装不同的jdk,不同平台的jvm对外暴露的是同样的接口,但是内部解释0和1的过程是不一样的,这就间接实现了跨平台。我们平常写代码就不用考虑不同平台兼容性的问题,jvm会帮你做,write once,run anywhere。鉴于此,我们也可以开发一种语言,只要能编译成字节码文件,就能借助jvm让其运行在操作系统上,就像scala。~笑脸~

3、语言本身的规范

这也是跨平台一个重要的原因。Java的基本数据类型的值域和行为都是由它自己定义的。

不管是在那种平台下运行,Java中的int都是32位二进制表示有符号整数,而float则总是遵循IEEE754浮点标准的32位浮点数。

在像C/C++这样的语言中,基本数据类型int的值域是由它的占位宽度决定的,而它的占位宽度则由平台决定的。这就是它不能跨平台的一个原因了。

java虚拟机怎么样

走向架构师,你必须了解的Java虚拟机高级特性

链接: https://pan.baidu.com/s/1hAPo19keNFHb9ycBctkU2A 密码: iayw

看完了你就知道Java虚拟机了 不要谢我 、

对了

记得点赞关注一下我头条号Java分布式

Java运行时区域,哪些区域是线程私有的哪些是共有的

JVM 运行时数据区域大致可以分为:程序计数器、虚拟机栈、本地方法栈、堆区、元空间、运行时常量池、直接内存等区域;就是下面这个样子的:

其中有些区域,随着 JDK 版本的升级不断调整,例如:

  • JDK 1.6,字符串常量池位于永久代的运行时常量池中;

  • JDK 1.7,字符串常量池从永久代剥离,放入了堆中;

  • JDK 1.8,元空间取代了永久代,并且放入了本地内存(Native memory)中。

以上几个区域,按照线程公有还是私有可分为:

  • 线程隔离:程序计数器、虚拟机栈、本地方法栈;

  • 线程公有:其它的都是线程共享的区域。

线程私有

1. 程序计数器

一个 CPU 在某个时间点,只能做一件事情,在多线程的情况下,CPU 运行时间被划分成若干个时间片,分配给各个线程执行;

程序计数器的作用就是记录当前线程执行的位置,当线程被切换回来的时候,能够找到该线程上次运行到哪儿了;所以程序计数器一定是线程隔离的。

2. 虚拟机栈和本地方法栈

  • 虚拟机栈:每个 Java 方法在执行的同时,会创建一个栈帧,用于存储局部变量表、操作数栈、常量池引用等信息;方法的调用过程,就是一个栈帧在 Java 虚拟机栈中入栈和出栈的过程;

  • 本地方法栈:和虚拟机栈很类似,区别在于虚拟机栈为 Java 方法服务,本地方法栈为 Native 方法服务;其中 Native 方法可以看做用其它语言(C、C++ 或汇编语言等)编写的方法;

  • HotSpot 虚拟机就选择了将虚拟机栈和本地方法栈合并在了一起;

  • 为了保证线程中的局部变量不被别的线程访问到,所以虚拟机栈和本地方法栈是线程隔离的。

线程公有

1. 堆区

对于堆栈的区别总结一句话:堆中存对象,栈中存基本数据类型和堆中对象的引用;一个对象的大小是可以动态变化的,而引用是固定大小的。

这么看就容易理解堆为什么是线程公有的了,省地儿啊。

2. 元空间区/方法区

方法区用于存放已被加载的类信息、常量、静态变量、即编译器编译后的代码等。

还有要注意的一点:方法区是 JVM 的规范,在 JDK 1.8 之前,方法区的实现是永久代;从 JDK 1.8 开始 JVM 移除了永久代,使用本地内存来存储元数据并称之为:元空间(Metaspace)。

3. 运行时常量池

Class 文件中的常量池,会在类加载后被放入这个区域。

另外在 JDK 1.7 之前,字符串常量池就在运行时常量池中,后来字符串常量池放入了堆中,而运行时常量池仍然在方法区(元空间区)中。

有兴趣的朋友可以自己测试一下,以死循环方式创建字符串常量,JDK 1.6 会报永久代 OOM ;JDK 1.7 会报堆区 OOM 。

4. 直接内存

也叫做堆外内存,并不是虚拟机运行时数据区的一部分,也不是Java 虚拟机规范中定义的内存区域。

JDK 1.4 加入的 NIO 类,引入了一种基于通道 ( Channel ) 与缓冲区 ( Buffer ) 的 I/O 方式,它可以使用 native 函数库直接分配堆外内存,然后通过堆上的DirectByteBuffer对象对这块内存进行引用和操作。

简单来说,直接内存就是 JVM 内存之外有一块内存区域,我们通过堆上的一个对象可以操作它;具体等讲到 NIO 部分的时候,再回来加深理解。

我将持续分享Java开发、架构设计、程序员职业发展等方面的见解,希望能得到你的关注;关注我后,可私信发送数字【1】,获取海量学习资料。