小白都能看懂的 JVM 知识,一文带你学会 JVM 内存模型!

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
img

正文

GC 是针对堆内存中没有引用的对象进行回收,可以手动也可以自动。

1.5.5 本地方法接口

因为 JVM 不能直接调用操作系统的功能,只能通过本地方法接口来调用操作系统的功能。

2. JVM 内存结构-程序计数器

==================

2.1 程序计数器的定义


Program Counter Register 即程序计数器(寄存器),用于记录下一条 Jvm 指令的执行地址。

2.2 操作步骤


javap 主要用于操作 JVM,javap -c 是对 java 代码进行反汇编操作。下图为通过先编译 demo.java 后,再执行 javap -c demo 的输出结果:

其中第一列为二进制字节码,即 JVM 指令,第二列为 java 源代码。第一列中的序号为 JVM 指令的执行地址。

JVM 会通过程序计数器记录下一条需要执行的 JVM 指令的地址(比如第一行的 0),然后交给解释器解析为机器码,最后交给 cpu(只能识别机器码),完成一行的执行。

想要执行下一行,继续让 JVM 的程序计数器记录下一条地址(比如第二行的 3),再交给解释器解析后给 cpu,以此类推执行结束。

2.3 特点


2.3.1 线程私有的

2.3.2 不会存在内存溢出

3. JVM 内存结构-虚拟机栈

=================

3.1 定义


虚拟机栈是每个线程运行所需要的内存空间,每个栈中由多个栈帧组成,每个线程中只能有一个活动栈帧(对应当前正在执行的方法),所有栈帧都遵循后进先出,先进后出的原则。

栈帧是每次调用方法时所占用的内存,在栈帧中保存的内容参数、局部变量、返回地址。

注 1:垃圾回收不涉及栈内存,因为栈内存是由方法调用产生的,当方法调用结束后会弹出栈。

注 2:栈内存不是分配的越大越好,因为物理内存是一定的,栈内存越大,可以支持更多的递归调用,但是可执行的线程数会越来越少。

注 3:方法的局部变量,当其没有逃离方法的作用范围时,是线程安全的;如果其引用了对象(比如静态变量,即共享变量,用对象作为参数的方法,返回值为对象的方法),并且逃离出了方法的作用范围,就需要考虑线程安全的问题了。

3.2 栈内存溢出


3.2.1 发生原因

(1)虚拟机栈中,栈帧过多(无限递归),如图 1 栈帧过多;

(2)每个栈帧所占用过大,如图 2 栈帧过大。

3.2.2 栈内存溢出小实验

3.2.2.1 栈帧过多的小实验

无限递归调用(栈帧过多)的小实验,method1()方法在主方法中无限调用自己,那么会发生什么情况呢?

答案很明显,程序崩溃了,产生了栈内存溢出错误,如下图所示:

-Xss:该参数规定了每个线程虚拟机栈的大小;

接着我们通过设置一个虚拟机栈的大小是 256k 试试会发生什么?

我们发现当我们调整了虚拟机栈的大小后执行了 4315 次方法后内存就溢出了,而调整虚拟机栈之前,我们是 23268 次,很明显我们可以通过-Xss 参数调整虚拟机栈的大小来控制内存的溢出情况。

3.2.2.2 线程运行诊断小实验

想象中的场景,大佬在疯狂输出,突然 CPU 爆表了,显示 CPU 占用过多,如何去定位哪行代码的问题,是的是哪行(大佬都很忙的好吗,当然要精确了,一分钟几千万上下的,O(∩_∩)O 哈哈~)?

Linux 环境下:

在后台运行 Stack_6 这个 java 字节码(.class)文件:

注:无论是否将 nohup 命令的输出重定向到终端,输出都将附加到当前目录的 nohup.out 文件中。

(1)通过 top 命令,查看进程(相当于任务管理器),发现了一个占用 CPU 达到 100%的可疑家伙,这还了得,赶紧瞅瞅具体发生了什么,还有没有王法,这让其他小伙伴还怎么愉快的玩耍,秒速纠错 ING。。。

top 命令,查看哪个进程占用 CPU 过高,返回进程号。

(2) 通过 ps H -eo pid,tid ,%cpu | grep 命令过滤任务管理器中的内容。

注:ps H -eopid,tid,%cpu |grep,是通过 ps 命令查看哪个线程占用 CPU 过高,返回进程 id,其中 pid 为进程 id,tid 为线程 id,%cpu 为 CPU 占用情况;

发现了罪魁祸首,这一串串心惊肉跳的红色。。。

(3) 通过 jstack 进程 id 查看,20389 这个有问题的进程中具体的情况。

注:jstack 进程 id,是通过 jstack 命令定位具体哪段代码出现占用 CPU 过高,注意 jstack 命令查找的线程 id 是 16 进制的,需要转换;

发现里面有一堆执行的代码,那么我们怎么找到具体是哪个家伙搞事情的呢?上图我们可以发现搞事情的线程是 20441,那么我们通过计算器将 20441 转换为 16 进制的 4FD9 再去试试,真相只有一个。

通过对比 nid(线程 id)4fd9,我们发现这个叫 thread1 的线程一直在运行(RUNNABLE 状态),并且查看到位置是位于 Stack_6.java 文件的第 11 行出现的问题。。。

现在我们回到源码中,在 Stack_6 文件的第 11 行,我们发现原来这里一直在执行死循环,终于找到你,还好我没放弃,奈斯~

4. JVM 内存结构-本地方法栈

==================

4.1 定义


由于 Java 本身有时候是无法直接和操作系统底层交互的,但有时候需要 Java 调用本地的 C 或 C++方法,所以此时本地方法栈应运而生,它们是一类带有 native 关键字的方法。

5. JVM 内存结构-堆

==============

5.1 定义


Heap 堆:是通过 new 关键字创建的对象存放在堆中

5.2 特点


5.2.1 线程共享

堆中存放的对象都是线程共享的,因此都是需要考虑线程安全问题的。

5.2.2 有垃圾回收机制

因为堆中存放的对象存放了大量的对象,因此给他配了个小助手——垃圾回收机制(可以调自动挡和手动挡哦~)。

5.3 堆内存溢出小实验


5.3.1 修改堆内存大小参数的小实验

继续幻想一个场景,当一个大佬开发完一个段代码的时候(当然一般大佬都是很自信的,我写的代码怎么可能有问题,不存在的。。。),但是测试可跑不了,稳妥起见咱们还是默默得搞测试试试嘛,安全第一。但是机器的内存就这么大,大佬肯定跑了很多次了,都没出现问题的,这不是找茬嘛。。。还是默默改下机子参数再试试吧(想去怼大佬,一定要拿出证据嘛~)。

-Xmx:JVM 调优参数之一,该参数表示 java 堆可以扩展到的最大值。下面上案例:

在执行了 26 次之后,果断的后台报了堆内存溢出错误。

下面通过-Xmx JVM 调优参数将堆内存调小至 8m,再试试会发生什么呢?

操作基本和栈内存溢出的时候的案例一样,次数明显变小了,只调用了 17 次就出现了堆内存溢出错误了。

5.3.2 堆内存诊断的小实验

jps 工具:查看当前系统中有哪些 java 进程

jmap 工具:查看堆内存的占用情况 jmap -heap 进程 id

jconsole 工具:图形化的工具,拥有多功能的监测功能,可以连续监测。

总结

其他的内容都可以按照路线图里面整理出来的知识点逐一去熟悉,学习,消化,不建议你去看书学习,最好是多看一些视频,把不懂地方反复看,学习了一节视频内容第二天一定要去复习,并总结成思维导图,形成树状知识网络结构,方便日后复习。

这里还有一份很不错的《Java基础核心总结笔记》,特意跟大家分享出来

目录:

部分内容截图:

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
础核心总结笔记》,特意跟大家分享出来

目录:

[外链图片转存中…(img-ANIT5QQt-1713467184541)]

部分内容截图:

[外链图片转存中…(img-PLIls9a6-1713467184542)]

[外链图片转存中…(img-ezlfF9oO-1713467184543)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-5szD1zbv-1713467184544)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 18
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值