记JVM内容知识点

JVM虚拟机的位置

在这里插入图片描述
参考:https://blog.csdn.net/hello_cmy/article/details/105090758

JVM内存模型

在这里插入图片描述

类加载器

类加载器负责加载所有的类,其为所有被载入内存中的类生成一个java.lang.Class实例对象。一旦一个类被加载如JVM中,同一个类就不会被再次载入了。正如一个对象有一个唯一的标识一样,一个载入JVM的类也有一个唯一的标识。在Java中,一个类用其全限定类名(包括包名和类名)作为标识;但在JVM中,一个类用其全限定类名和其类加载器作为其唯一标识。例如,如果在pg的包中有一个名为Person的类,被类加载器ClassLoader的实例kl负责加载,则该Person类对应的Class对象在JVM中表示为(Person.pg.kl)。这意味着两个类加载器加载的同名类:(Person.pg.kl)和(Person.pg.kl2)是不同的、它们所加载的类也是完全不同、互不兼容的。

JVM预定义有三种类加载器,当一个 JVM启动的时候,Java开始使用如下三种类加载器:

  • 根类(启动类)加载器(bootstrap class loader):它用来加载 Java 的核心类,是用原生代码来实现的,并不继承自 java.lang.ClassLoader(负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类)。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
    下面程序可以获得根类加载器所加载的核心类库,并会看到本机安装的Java环境变量指定的jdk中提供的核心jar包路径:

public class ClassLoaderTest {
 
	public static void main(String[] args) {
		
		URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
		for(URL url : urls){
			System.out.println(url.toExternalForm());
		}
	}
}

运行结果:
在这里插入图片描述

  • 扩展类加载器(extensions class loader):它负责加载JRE的扩展目录,lib/ext或者由java.ext.dirs系统属性指定的目录中的JAR包的类。由Java语言实现,父类加载器为null。

  • 系统类(应用程序)加载器(system class loader):被称为系统(也称为应用)类加载器,它负责在JVM启动时加载来自Java命令的-classpath选项、java.class.path系统属性,或者CLASSPATH换将变量所指定的JAR包和类路径。程序可以通过ClassLoader的静态方法getSystemClassLoader()来获取系统类加载器。如果没有特别指定,则用户自定义的类加载器都以此类加载器作为父加载器。由Java语言实现,父类加载器为ExtClassLoader。

类加载器加载Class大致要经过如下8个步骤:

  1. 检测此Class是否载入过,即在缓冲区中是否有此Class,如果有直接进入第8步,否则进入第2步。
  2. 如果没有父类加载器,则要么Parent是根类加载器,要么本身就是根类加载器,则跳到第4步,如果父类加载器存在,则进入第3步。
  3. 请求使用父类加载器去载入目标类,如果载入成功则跳至第8步,否则接着执行第5步。
  4. 请求使用根类加载器去载入目标类,如果载入成功则跳至第8步,否则跳至第7步。
  5. 当前类加载器尝试寻找Class文件,如果找到则执行第6步,如果找不到则执行第7步。
  6. 从文件中载入Class,成功后跳至第8步。
  7. 抛出ClassNotFountException异常。
  8. 返回对应的java.lang.Class对象。

摘自:https://blog.csdn.net/m0_38075425/article/details/81627349

双亲委派机制

在这里插入图片描述
双亲委派机制得工作过程:
1-类加载器收到类加载的请求;
2-把这个请求委托给父加载器去完成,一直向上委托,直到启动类加载器;
3-启动器加载器检查能不能加载(使用findClass()方法),能就加载(结束);否则,抛出异常,通知子加载器进行加载。
4-重复步骤三;
摘抄自上海小墨子https://www.cnblogs.com/parent-absent-son/p/9872443.html

沙箱安全机制

Java安全模型的核心就是Java沙箱(sandbox),什么是沙箱?沙箱是一个限制程序运行的环境。沙箱机制就是将 Java 代码限定在虚拟机(JVM)特定的运行范围中,并且严格限制代码对本地系统资源访问,通过这样的措施来保证对代码的有效隔离,防止对本地系统造成破坏。
摘抄自不怎么nice

native

内容:https://www.cnblogs.com/Qian123/p/5702574.html

JVM 程序计数器

程序计数器是一块较小的内存空间,它的作用可以看作是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。- - 摘自《深入理解Java虚拟机》
内容:https://blog.csdn.net/leaf_0303/article/details/78953669

JVM方法区

方法区是被所有所有线程共享,所有字段和方法字节码,以及一些特殊方法,如构造函数、接口代码也在此定义,简单的说,所有定义方法的信息都保存在该区域,此区域属于共享区间
静态变量、常量、类信息(构造方法、接口定义)、运行时的常量池在方法区中,但是实例变量存在堆内存中和方法区无关
内容:https://www.cnblogs.com/natian-ws/p/10731270.html

参考:https://www.cnblogs.com/wade-luffy/p/5753057.html

堆(heap)

堆内存划分:
在这里插入图片描述
JVM内存划分为堆内存和非堆内存,堆内存分为年轻代(Young Generation)、老年代(Old Generation),非堆内存就一个永久代(Permanent Generation)。
年轻代又分为Eden和Survivor区。Survivor区由FromSpace和ToSpace组成。Eden区占大容量,Survivor两个区占小容量,默认比例是8:1:1。
堆内存用途:存放的是对象,垃圾收集器就是收集这些对象,然后根据GC算法回收。
非堆内存用途:永久代,也称为方法区,存储程序运行时长期存活的对象,比如类的元数据、方法、常量、属性等。

在JDK1.8版本废弃了永久代,替代的是元空间(MetaSpace),元空间与永久代上类似,都是方法区的实现,他们最大区别是:元空间并不在JVM中,而是使用本地内存。
元空间有注意有两个参数:

  • MetaspaceSize :初始化元空间大小,控制发生GC阈值
  • MaxMetaspaceSize : 限制元空间大小上限,防止异常占用过多物理内存

摘自:https://blog.csdn.net/lingbo229/article/details/82586822

永久代和方法区

1、方法区

方法区(Method Area)是jvm规范里面的运行时数据区的一个组成部分,jvm规范中的运行时数据区还包含了:pc寄存器、虚拟机栈、堆、方法区、运行时常量池、本地方法栈。主要用来存储class、运行时常量池、字段、方法、代码、JIT代码等。运行时数据区跟内存不是一个概念,方法区是运行时数据区的一部分。方法区是jvm规范中的一部分,并不是实际的实现,切忌将规范跟实现混为一谈。

2、永久代
  永久带又叫Perm区,只存在于hotspot jvm中,并且只存在于jdk7和之前的版本中,jdk8中已经彻底移除了永久带,jdk8中引入了一个新的内存区域叫metaspace。并不是所有的jvm中都有永久带,ibm的j9,oracle的JRocket都没有永久带,永久带是实现层面的东西,永久带里面存的东西基本上就是方法区规定的那些东西。

3、区别
  方法区是规范层面的东西,规定了这一个区域要存放哪些东西,永久带或者是metaspace是对方法区的不同实现,是实现层面的东西。

JVM GC垃圾回收机制

堆是Jvm立马很重要的一个区域,也是跟方法区一样属于全部线程都可以共享访问的一个区域,在堆中存储了大量的Java对象信息,但凡是new出来的对象都存放在这里,并且可以通过jvm提供的-Xmx和-Xms来调节堆的大小。其中-Xmx是堆的最大值是多少,-Xms是堆的最小内存,如果两者一致,则这个Jvm的堆大小就不能弹性伸缩。
在这里插入图片描述
事实上,堆内部也划分除了多个区域,分别是新生代、老年代以及持久代。这其中新生代又分为Eden和Survivor01、Survivor02等等。为什么要这么划分,这就涉及到了Jvm的GC回收策略了。

新生代中存储了所有新创建的对象,一个新对象创建OK首先是存放在Eden区域的,当Eden区域快要被填满时,就会自动触发Jvm的GC机制,GC会回收一些空闲的对象,再将幸存下来的其他对象转移到Survivor01中去,同样,如果01也满了 再次对01这一区域进行GC回收,将幸存者放入Survivor02区域中去。一旦在Survivor02中历经磨难多次存活超过15次,就会将其转移至老年代中去。至于持久代中,则主要存储一些常量池、方法区等数据。相关参数如下:

-Xmx:最大堆内存,如:-Xmx512m
-Xms:初始时堆内存,如:-Xms256m
-XX:MaxNewSize:最大年轻区内存
-XX:NewSize:初始时年轻区内存.通常为 Xmx 的 1/3 或 1/4。新生代 = Eden + 2 个 Survivor 空间。实际可用空间为 = Eden + 1 个 Survivor,即 90%
-XX:MaxPermSize:最大持久带内存
-XX:PermSize:初始时持久带内存
-XX:+PrintGCDetails。打印 GC 信息
-XX:NewRatio 新生代与老年代的比例,如 –XX:NewRatio=2,则新生代占整个堆空间的1/3,老年代占2/3

-XX:SurvivorRatio 新生代中 Eden 与 Survivor 的比值。默认值为 8。即 Eden 占新生代空间的 8/10,另外两个 Survivor 各占 1/10
摘自:https://blog.csdn.net/qq_30683329/article/details/80465132

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值