初识JVM

JVM探究

  • 请谈谈你对JVM的理解,Java8虚拟机和之前有什么变化更新?
  • 什么是内存溢出(OOM),什么是栈溢出?怎么分析?
  • JVM的常用调优参数有哪些?
  • 内存快照如何抓取,怎么分析Dump文件?
  • 谈谈JVM中,你对类加载器的认识?

1、JVM的体系结构

2、类加载器和双亲委派机制

要了解双亲委派机制得先了解个概念:

类加载器:“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块成为“类加载器”。

通俗的讲,虚拟机是根据类的全限定名来加载类的,那么有个问题,如果同时存在两个或多个全限定名完全一致的情况下。该如何选择加载哪个类。这就是双亲委派机制要做的工作。

双亲委派机制得工作过程:

1-类加载器收到类加载的请求;

2-把这个请求委托给父加载器去完成,一直向上委托,直到启动类加载器;

3-启动器加载器检查能不能加载(使用findClass()方法),能就加载(结束);否则,抛出异常,通知子加载器进行加载。

4-重复步骤三;

详细见:双亲委派机制

3、沙箱安全机制

什么是沙箱?
 Java安全模型的核心就是Java沙箱(sandbox),什么是沙箱?沙箱是一个限制程序运行的环境。沙箱机制就是将 Java 代码限定在虚拟机(JVM)特定的运行范围中,并且严格限制代码对本地系统资源访问,通过这样的措施来保证对代码的有效隔离,防止对本地系统造成破坏。沙箱主要限制系统资源访问,那系统资源包括什么?——CPU、内存、文件系统、网络。不同级别的沙箱对这些资源访问的限制也可以不一样。

4、Native、pc寄存器、方法区

Native

native:凡是带了native关键字的,说明Java的作用范围达不到了,需要调用本地接口方法(其他语言的库)。

1、带了native关键字的,首先会进入运行时数据区中的本地方法栈中,然后调用相应的本地方法接口JNI(Java Native Interface),从本地方法库中找出相应的方法。

2、JNI的作用:扩展Java的使用,融合不同的编程语言为Java所用!最初是为了融合c、c++。

3、它在内存区域中专门开辟了一块标记区域:Native Method Stack(本地方法栈),登记native方法。在最终执行的时候,通过JNI加载本地方法库中的方法。

PC寄存器

程序计数器 program Counter Register

​ 每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向下一条指令的地址,就是即将执行的指令代码),在执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计。

方法区 Method Area

​ 方法区是被所有线程共享的,所有的字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单的说,所有定义的方法的信息都保存在该区域,此区域属于共享区间

​ 静态变量、常量、类信息(构造方法、接口定义)、运行时的常量池都存放在方法区中,但是实例变量存在堆内存中,和方法区无关。

5、栈

先进后出

栈内存:主管程序的运行,生命周期和线程同步。线程结束,栈内存也就释放。所以说,不存在垃圾回收的问题。

栈内存存储:8大基本类型、对象引用、实例的方法引用

深入理解请看

6、堆

heap,一个JVM只有一个堆内存,堆内存的大小是可以调节的。

当Java程序创建一个类的实例或者数组时,都在堆中为新的对象分配内存。bai虚拟机中只有一个堆,所有的线程都共享他。Java中所有的对象都存放在堆中,包括class对象和异常对象。

其实,堆内存细分为三个区域:

  • 新生区(伊甸园区eden、幸存0区survivor0、幸存1区survivor1)

    类诞生、成长、甚至死亡的地方

    • 伊甸园区,所有的对象都是在伊甸园区new 出来的
    • 幸存区(0,1)
  • 养老区 old

​ 经过gc垃圾回收幸存留下来的对象存放在这。

​ 其实,99%的对象都是临时对象!

  • 永久区(元空间) permanent

    这个区域是存放的常驻内存的。用来存放JDK自身携带的class对象。interface元数据,存储的是Java运行时的一些环境或类信息,这个区域不存在垃圾回收!关闭KVM虚拟就会释放这个区域的内存~

在JDK7以及其前期的JDK版本号中。堆内存通常被分为三块区域Nursery内存(young generation)、长时内存(old generation)、永久内存(Permanent Generation for VM Matedata),显演示样例如以下图:

img

7、GC垃圾回收

JVM在进行GC时,并不是对这三个区域统一回收。大部分时候,都是在新生区

  • 新生区
  • 幸存区
  • 老年区

GC分为两类:轻GC(Miner GC,回收新生区和幸存区中的垃圾)重GC(Full GC,全局回收垃圾,包括老年区)

GC的算法:标记清除法、标记压缩法、复制算法、引用计数法。

引用计数法:

设置一个计数器,记录对象的调用次数,对此来进行垃圾回收。

复制算法:

每次GC后,将新生区和幸存from区中活下来的对象复制存放到幸存to区,同时清空新生区和幸存from区,

此时from区清空后变为to区,to区被复制过去对象后变为了from区。

谁空谁是to区

经历过15次GC后,仍然留下来的对象会转移到老年区中。

标记清除压缩法:

标记清除

1、先将活着的对象进行标记,

2、然后把没有标记的对象删除掉

标记压缩(标记整理)

1、先将活着的对象进行标记

2、然后将标记的对象向前移动压缩。

总结:

内存效率:复制算法>标记清除算法>标记压缩算法(时间复杂度)

内存整齐度:复制算法=标记压缩算法>标记清除算法

内存利用率:标记压缩算法=标记清除算法>复制算法

posted @ 2020-11-22 13:38  小胖学java  阅读(152)  评论(0编辑  收藏  举报