JVM(1)

1.导读:

本篇文章我们主要谈的话题为JVM是什么、能干什么、它的内存结构、内存泄露和内存溢出(00M)

2.JVM是什么:

  • JVM是Java Virtual Machine 的缩写,翻译过来叫做Java虚拟机。
  • 虚拟机是的是用软件来模拟具有完整硬件功能的、运行在一个完全隔离环境中的计算机系统。
  • 要清楚JVM是经过裁剪之后的虚拟机,它是一个用来执行字节码指令集的软件。
  • 在Java进程启动时会创建一个Java虚拟机,用来解释执行字节码指令,将字节码指令翻译为机器码,最终由系统调度CPU去执行机器码。
  • 不同虚拟机的实现,只要运用符合字节码规范的代码都能做到。

3.JVM能干什么:

  • 简单讲,我们在执行一个Java代码的时候离不开JVM。Java代码在执行的时候,先将java代码进行编译,生成 .class字节码文件,在进行运行。在运行的时候就要牵扯将字节码文件如何转化成机器码,进而让CUP去执行。
  • 下边用一张图来展示java代码是如何运行的。
    在这里插入图片描述
  • 经过上边图的展示,我们可以知道:在一个Java进程启动之后,就会创建一个Java虚拟机。它是为了能将编译好的字节码指令转换成机器码让CPU执行,所以起到翻译的作用。

4.类加载:

  • 上边谈了在启动一个Java进程的时候,要是这个类没有进行加载则要进行类加载。那么类加载发生的时机和类加载做的事情是什么?

  • 类加载时机:
    (1)new对象时
    (2)读写静态变量时
    (3)调用静态方法时
    (4)牵扯到父类子类是,要是子类想进行类加载,先对父类进行加载。
    (5)java类名启动的入口类

  • 类加载干的事情
    (1)把字节码加载到java进程的方法区,里边包含类的信息,方法信息等等。
    (2)在堆上生成一个Class类对象,作为方法区类信息的访问入口。

5.JVM内存结构:

  • JVM在运行java程序的时候,会将它管理的内存进行区域划分,每个区域都用自己的作用。有的区域的生命周期和虚拟机的创建退出有关,有的区域是和具体的线程相关。下边先展示一下JVM在运行java程序时的区域划分。
    在这里插入图片描述

1)程序计数器:(线程私有)

  • 首先是六个里边占据内存空间最小的一个区域。
  • 是六个区域里边唯一不会OOM的区域。
  • 是当前线程的行号指示器,起的是指引作用。在线程进行时间片轮转的时候,切换出去后还是要切换回来。所以就是记录一下行号,在下次切换回来的时候能找到切换出去的位置。

2)JVM栈:(线程私有)

  • JVM栈描述的是java方法运行时的内存模型.
  • 每个方法的执行都会创建一个栈帧结构,用来储存局部变量表、操作数栈、方法出口等。局部变量表存的是:基本数据类型、对象引用等
  • 栈帧:值的是线程每调用执行一个方法的时候都会进行入栈和出栈操作。方法进入时创建栈帧(入栈),方法返回时(出栈)。
  • 它的生命周期和线程的生命周期相关联。线程在启动时JVM栈会创建,线程在销毁时JVM栈会销毁。
  • 它会存在两个异常:
    (1)StackOverflowError:原因是在线程启动调用方法时,如果一直调用没有返回,调用的深度已经超过了JVM给定的深度,就会出现这样的异常。实际中,就是在我们写递归的时候,要是没有递归出口,就会出现这种异常。
    (2)会出现OOM:原因是在JVM栈扩展时,在无法申请到足够内存的时候就会出现内存溢出异常

3)本地方法栈:(线程私有)

  • 看字面意思,就是把上边将的JVM换成了本地方法了。因此它的用途和JVM栈是相似的。JVM栈是虚拟机执行Java方法服务的,本地方法栈是虚拟机执行本地方法服务.
  • 它也可能出现StackOverflowError和OOM异常。原因和上边一样。

4)Java堆(线程共享)

  • 在虚拟机启动的时候,就会自动创建出来,此时创建出的堆所占据的内存称之为堆的最小值。
  • 堆是六个里边占据内存模块最大的一块区域,里边存是所有对象的实例或者数组。
    -堆是垃圾回收器管理下最主要的区域,因此叫做“GC堆”。
  • Java堆在物理上可以不连续,因此Java堆再虚拟机中是能够进行扩展的。启动虚拟机所开辟的堆的内存叫做堆的最小值(-Xms设置最小值,-Xmx设置最大值)
  • 要是堆的内存够用,就要进行扩展。要是已经扩展到能允许的最大值并且在经过GC之后要是还不够用,就会出现OOM。

5)方法区:(线程共享)

  • 方法区里边存的是已被虚拟机加载好的类信息、常量、静态变量、及时编译后的代码数据。
  • 里边存在GC,会回收常量和类型(无用的)。
  • 老版本的JDK里边没有进行回收,就会存在内存泄露。

6)运行时常量区(线程共享)

  • 属于方法区的一部分,里边有字符串常量池,用于存放字面量和直接引用。

6.内存泄露和内存溢出:

(1)内存泄露:(Memory Leak):

  • 定义:指进程在运行过程中,对内存进行不断的申请,但是却没有进行及时的释放,导致内存里边存储的无用数据越来越多,进而导致可用内存变得越来越少。

  • 形象理解:有一家店,店的面积是有限的。现在顾客陆续进来,顾客进来后没有点餐,而是在那里一直等。伴随着这种顾客的不停增加,导致店的可用位置越来越少。最后导致店里坐满,其他的顾客不能进来。这样的场景就叫内存泄露,长时间的内存泄露会导致OOM。

  • 出现场景:拿用户登录举例子,在用户进行登录的时候,会自动创建出一个Session并保存。创建Session的时候就要占据内存,但是只要是用户没有点击注销或者退出登录的话,这个Session会一直存在。伴随这这种用户的增多,就会不断的创建Session,导致可用内存不断减少。而前边创建好的Session又没有干事情,就一直在哪里等待。这就是内存泄露,可以看出一两次的内存泄露影响到不是很大,但是无数次的内存泄露会导致OOM。

  • 如何解决:还是拿上边顾客用餐例子寻求解决方法。我们很容易能想出:要是顾客进来超过一定时间不点餐,我们就劝他们去别的地方消费。对应的措施就是:在程序代码上进行优化,规定一个时间,要是在这段时间内存上的数据没有用上,就把它释放掉,并且定时扫描并清理不用的数据。或者直接重启进程,就会从新进行分配。

  • 内存泄露在随着时间的推移势必会导致内存溢出。

(2)内存溢出(Out Of Memory)

  • 定义:简单的将就是你自己的空间不够别人来用了,就会出现内存溢出。
  • 形象理解: 你开的店最多容纳30人同时用餐,但是现在有一个团体他们一共有100人想一块进来,这时你的店不够大,没法一次性容纳这些人同时用餐,这就叫做内存溢出。
  • 内存泄露可能会导致内存溢出,但是内存溢出却不一定是内存泄露导致的。
  • 出现场景:上边也说了,在Java虚拟机运行起来之后,线程共享的区域都有可能会出现内存溢出。在堆里边存放数据,要是扩展到他能允许的上线,并且GC之后还是不够用的话,就会导致内存溢出。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值