jvm梳理

文章详细介绍了JVM的工作原理,包括通过javac编译生成class文件,类加载器的层次结构(引导加载器、扩展加载器、系统加载器和自定义加载器)以及双亲委派机制。接着,讨论了虚拟机栈、本地方法栈、堆(新生代、老年代、伊甸园、幸存区)以及方法区的作用。此外,还提到了程序计数器和两种常见的错误:StackOverFlowError和OOM(内存溢出)及其解决方案。
摘要由CSDN通过智能技术生成

jvm是一个虚拟机,用于运行java代码,类的编译到运行主要为一下:

通过javac.exe编译,产生class文件,然后通过类加载器加入jvm:

类加载器

引导加载器:使用c++编写,负责java的核心库,只能底层调用,无法直接获取。

扩展加载器:在jdk\bin\ext文件下,拓展的jar包,

系统加载器:最常用的加载器,它负责加载用户路径(ClassPath)上所指定的类库。我们自己编写的代码以及使用的第三方的jar包都是由它来加载的。

自定义加载器:就是我们自己编写的类。

类加载器有一个很重要的机制:

双亲委派机制

是为了程序的安全产生的,他的效果是:

会一直委派到最底层的加载器:

引导加载器<——扩展加载器<——系统加载器<——自定义加载器<——代码

然后一级一级寻找类,为什么这样可以保证安全?

主要是为了保证jdk的核心类不被修改。

所以双亲委派机制解决了这个问题,程序直接用原来的类,因为从逻辑上知道,这个类是对的。

虚拟机栈:

里面主要存放:对象引用地址+8大基本类型

存放程序的执行步骤,为什么要怎么说呢?

我们都知道,main方法是最先执行的,那么,它到底什么时候结束的呢?我想这个问题大家都知道,main方法是最后结束的,所以这就说明了,程序调用时用栈实现的。

  本地方法栈:

存放调用的本地接口方法,如果大家查看过多线程的类,会发现,底层开启线程并不是java实现的,调用了一个方法:

native就是用来标记该方法为调用本地方法,也就是本地的c++方法,所以jvm的底层其实就是c++。

然后我们就来说一下堆:

这玩意就是jvm核心的地方,也是最麻烦的地方

堆中包含如下:

堆中主要存放实力对象!

 新生代,老年代,伊甸园、幸存区是啥呢?

新生代指的是在程序运行时,创建的类,会被GC垃圾清理机制清理掉,而老年代指的是有些类经常使用,不会被清理。

一旦这个类多次被使用了,就会放去幸存区,如果再多次调用,就会放去老年区。

也就是说,伊甸园>幸存区,GC优先清理伊甸园,GC清理机制分为普通清理加强清理,当普通GC清理不了的时候,就调用加强GC清理。所以中99%的垃圾处理都在堆中处理,栈中是不会存在的,因为栈一旦使用,就出栈了。

GC清理机制用白话说挺简单,就是判断改类是否被用,一个类被调用时,栈就会指向它,是一个双向,类似双向链表,所以一旦为null,就可以回收啦~

方法区:主要放static修饰的变量,方法,final常量,类的信息

这里还有一个知识点,堆、方法区是线程共享的,谁都可以调用,也就是为什么,static全部地方都可以使用。

程序计数器:

看到这个,我就想起了cpu也有这玩意,用来记录执行的指令,它们都是一样的效果,这玩意也是拿来保存指令,记录下一条指令是啥。

 然后就是写过递归的同志都遇见过的报错:StackOverFlowError栈溢出

这玩意就是调用过多的方法,导致栈爆满,一般情况都是死递归调用,闭环。

还有一个就是学习的时候根本遇不到,只能刻意的创建(因为学习肯定不会创建这么多的对象)

OOM内存溢出,因为对象创建太多了,堆都装满了,死循环new对象。。。。

解决办法就是先提高堆的内存,看看是否再次报错,用idea就是如下:

 然后就是导出dump文件,使用jprofiler软件查看,具体看视频: 

9、使用JPofiler工具分析OOM原因_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值