JVM---体系结构(一)

体系结构概览

在这里插入图片描述

注意:

  • java源文件通过javac编译成java字节码文件.class
  • .class文件打开,他的开头是cafe babe,所以虚拟机才能识别
  • 通过类加载器ClassLoader加载.class文件,将class文件放入内存中各个区域
  • 程序计数器、JAVA栈、本地方法栈是线程独有的,不受GC管理。栈中是没有垃圾的因为栈用完自动释放。
  • 堆里面垃圾最多、方法区中有少量垃圾。受GC管理
  • 所谓的JVM调优,就是针对堆和方法区。
  • 方法区里面并不是方法,而是类的模版。
  • java8 方法区又称为非堆区,在内存结构中称为“元数据”。
  • 灰色部分,是线程私有的,占用内存非常少,几乎不存在GC垃圾回收。

类加载器

在这里插入图片描述

问:什么是类加载器?

  • 类加载器是用来加载类(class文件)的
  • 类加载器也是一个类:ClassLoader
  • 类加载器可以被加载到内存,也是通过类加载器完成的

问:类加载器有哪几种?

  • 系统自带的有三种:
  • 启动类(根)加载器(BootStrap) C++写的,java程序获取不到
  • 扩展类加载器(Extension) Java写的
  • 应用程序类加载器(AppClassLoader)Java也叫系统类加载器,加载当前应用的classpath的所有类。
  • 用户自定义加载器:
  • Java.lang.ClassLoader的子类,用户可以定制类的加载方式。

问:什么叫双亲委派机制?

  • 浅显理解:我爸是李刚,有事儿找我爹,要用到某个类,先去根加载器中找,找的到就用,如果找不到,再去扩展类加载器中找,还是没有,就去应用程序类加载器中找。
  • 步骤:
  1. 类加载器收到类加载的请求
  2. 将这个请求向上委托给父类加载器去完成,一直向上委托,知道启动类加载器
  3. 启动加载器检查是否能加载当前这个类,能加载就结束,使用当前的加载器,否则,抛出异常,通知子类进行加载。(ClassNotFound)
  4. 重复步骤3

在这里插入图片描述

问:沙箱安全机制是什么?

  • java安全的核心就是沙箱,沙箱就是限程序运行的环境,只能在jvm限定范围内运行,并且严格控制代码对本地系统资源的访问。
  • 沙箱安全机制是由基于双亲委派机制上 采取的一种JVM的自我保护机制,假设你要写一个java.lang.String 的类,由于双亲委派机制的原理,此请求会先交给Bootstrap试图进行加载,但是Bootstrap在加载类时首先通过包和类名查找rt.jar中有没有该类,有则优先加载rt.jar包中的类,因此就保证了java的运行机制不会被破坏.

问:为什么有沙箱安全机制?

  • 防止恶性代码污染源代码

本地方法栈

在这里插入图片描述

注意:

  • 进程线程这种概念是系统级的,不是语言级的。
  • 看源码后,只要方法前加上了native,说明这是一个跟java无关的要调底层操作系统或者是第三方C语言函数库的方法,java搞不定,需要别的系统和语言提供方法来介入,需要求助于外援。
  • 本地方法栈(Native Method Stack):装native方法专用的栈,这是一个特殊的栈—(Native栈)
  • JNI(java native interface):扩展java的使用,融合不同的编程语言为java所用。

问: 为什么源码中会有native方法的声明,却没有实现呢(实现交给了底层的第三方函数库来实现)?

  • 因为Java诞生初期,1995年10月,那个时候最盛行的语言是C语言,相当于老大,每个语言需要向他交保护费(Java要留出一个接口向C语言妥协),所以有了native。

PC寄存器

程序计数器(Program Counter Register

  • 简单理解:就是一个指针,一个方法运行完了,指向下一个方法。
  • 每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中方法字节码(用来存储指向一条指令的地址,也就是即将要执行的指令代码),在执行引擎读取下一条指令的时候,是一个非常小的空间,几乎可以忽略不计,
  • PC寄存器:里面存的就是下一个将要执行的的方法的指针。

方法区

  • 方法区就是被所有的线程共享,所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单说,所有定义的方法的信息都保存在这个区域,此区域属于共享空间
  • 静态变量,常量,类信息(构造方法,接口定义),运行时的常量池存在方法区中,但是实例变量存在堆内存中,和方法区无关。
  • static ,final,Class,常量池。
  • 方法区存储了每一个类的结构信息,就是模板的意思。
  • 就是一套规范,在不同的虚拟机里头实现是不一样的,最典型的就是永久代(PermGen space)和元空间(Metaspace)

  • 栈也叫栈内存,主管java程序的运行,是在线程创建的时候创建,他的生命周期也就是线程的生命周期,线程结束,栈内存释放,对于栈来说,不存在垃圾回收问题,线程一结束,栈就释放了,
  • 栈中存储的有
  1. 本地变量:八种基本类型变量+对象的引用变量。
  2. 栈操作:记录出栈,入栈的操作。
  3. 栈帧数据:包含类文件,方法等。。。

栈帧结构:

  • 方法索引
  • 输入输出参数
  • 本地变量
  • Class File引用
  • 父帧
  • 子帧

在这里插入图片描述

注意:

  • java方法进入虚拟机之后,就成为了栈帧
  • Main方法是一切程序的入口,它永远被压在栈底。
  • 递归调用:不断地往栈中压自身的方法,由于栈内存有限,会导致栈溢出,出现StackOverflowError,它是Error错误,不是异常。

在这里插入图片描述
在这里插入图片描述
注意:

  • java 7之前堆内存:新生代,老年代,永久区
  • java 8以后堆内存:新生代,老年代,元空间
  • 一个堆空间物理上分为新生代,老年代两部分,逻辑上分为新生代,老年代,元空间三部分。

栈+堆+方法区的交互关系

在这里插入图片描述

  • HotSpot是使用指针的方式来访问对象,java堆中会存放类元数据的地址,reference存储的就直接是对象的地址。

猜你喜欢

转载自blog.csdn.net/weixin_44861399/article/details/106547346