写点什么

JVM 基本概念

  • 2022 年 4 月 16 日
  • 本文字数:2176 字

    阅读完需:约 7 分钟

java.lang.ClassLoader 的子类,用户可以自定义类的加载方式。


2)执行引擎 (Execution Engine)


执行引擎,负责解释命令,提交操作系统执行 Java 开源项目【ali1024.coding.net/public/P7/Java/git】


3)JVM 内存区(运行时数据区):


1、方法区(Method Area)


方法区是被所有的线程共享。方法区存储了每个类的信息(类的名称,方法信息,字段信息)、静态变量,常量池,以及编译后的代码。


Hotspot 虚拟机中,方法区是存在永久代中的。


方法区中存放的是类的字节码内存块。


类信息


修饰符(public final)


是类还是接口(class , interface)


类的全限定名(package.A.class)


类的直接父类的全限定名称(package.Parent.class)


类的直接父接口的全限定名数组(java/io/Serializable)


字段信息


修饰符:(private, public)


字段类型:(java.lang.String)


字段名称:(name)


类似:private String name;


方法信息


修饰符 (private, public static final)


返回值 (java/lang/String.class)


方法名称 (getMethod)


参数用的局部变量的大小以及操作栈的大小


异常表 (throws Exception)


方法体 (方法内容)的字节码


常量池


直接常量(各种基本数据类型的常量池) public final int age=12; public final String name=‘’;


方法名、方法描述符、类名、字段名,字段描述符的符号引用


静态变量


静态字段:public static String name=’’


一个到类加载器(classloader)的引用


存储了加载了自己的 class(A.class)的 ClassLoader 的引用。ClassLoader 的实例,存放在 jvm 的堆中。


虚拟机在加载 class 的时候,会在方法区字节码中存在一个指向加载自己的 classloader 的引用。


一个 class 对象的引用


ClassLoader 加载这个类的时候,从磁盘上将 a.class 加载到 jvm 的方法区,方法区中的字节内存块,会在 new 的时候使用。然后在内存 堆中生成一个 a 的字节码对象。在方法区的字节码中存在一个指向堆的 class 对象的引用。


一个 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》开源 指向被当前类的字节码实例的对象(堆空间)的引用。


方法表


这个类的所有的实例可能被调用的所有实例方法的直接引用。


2、Java 栈区(VM stack)


(1)栈内存是线程独享的。


(2)是在创建线程的时候创建。他的生命周期,随线程的生命周期。线程结束,栈的内存也就释放了。生命周期跟线程一致。


(3)8 种基本类型的变量,对象的引用变量,实例方法


(4)栈存储本地变量(输入参数,输出参数,方法内的局部变量) 栈操作(记录出栈,入栈的操作)


在启动一个线程的时候,jvm 虚拟机就会为每一个线程分配一个栈空间,栈空间是有一个一个的栈帧组成的 (栈帧是栈空间的最小单元,一个栈帧代表一个执行的方法)。


当前线程当前执行的某个方法叫做当前方法,当前方法使用的栈帧叫做当前栈帧,当前方法使用的类叫做当前类,当前类的常量池叫做当前常量池。线程在执行一个方法时会监控当前类以及当前类的常量池。


当线程调用一个 java 方法的时候,jvm 就会在当前线程的栈中压入一个栈帧。执行这个方法时,用这个栈帧存储参数,局部变量,中间运算结果等。


java 中的方法以两种方式结束,一种正常返回 return,一种通过抛出异常。两种方式返回时,jvm 就会将当前栈帧弹出释放掉,上一个栈帧就是当前栈帧(栈帧中会记录上一个栈帧的地址以及下一个栈帧的地址)。


栈空间是线程独有的,其他线程是不能访问的。


JVM 栈空间包含三部分(局部变量表,操作数栈,帧数据区)


局部变量表:


包括参数和局部变量以及中间变量。


局部变量是一个以字长为单位的数组,数组长度从 0 开始。类型 short, byte, char 在存储之前要转换成 int 值。而 double, long 类型的值占两个字长,一个字长占 4 个字节。


调用一个方法时,从他的类型信息中得到此方法(栈帧)局部变量区和操作数栈的大小,并根据此分配内存。


如上图,将参数以及局部变量压入局部变量表(数组)中,如果在执行过程中产生中间变量,同样也压入局部变量数组中。


特别注意:如果是非静态方法,局部变量数组中的 0 位是当前对象的引用


操作数栈:


操作数栈也被分配位一个以字长为单位的数组。和局部变量数组不同的是不是通过索引来进行访问的,而是通过入栈和出栈进行访问。


如下举例:


(1)先把 a=100 压入栈。


(2)再把 b=98 压入栈。


(3)执行 a+b,将 a,b 两个数值出栈,并把执行结果 198 压入栈。


(4)把中间变量执行结果存入局部变量数组中。


动态链接:


栈帧 内部包含一个 指向运行时常量池的引用,用来支持当前方法的执行。


class 文件中的常量存在大量的符号引用(标识常量),这些引用在类加载阶段,或者在第一次使用的时候转换成直接引用(指向数据所存的堆中的地址的指针),这种转换称为静态链接。另外一部分在运行期间才转换成直接引用,这一部分叫做动态链接。

最后

关于面试刷题也是有方法可言的,建议最好是按照专题来进行,然后由基础到高级,由浅入深来,效果会更好。当然,这些内容我也全部整理在一份 pdf 文档内,分成了以下几大专题:


  • Java 基础部分



  • 算法与编程



  • 数据库部分



  • 流行的框架与新技术(Spring+SpringCloud+SpringCloudAlibaba)



这份面试文档当然不止这些内容,实际上像 JVM、设计模式、ZK、MQ、数据结构等其他部分的面试内容均有涉及,因为文章篇幅,就不全部在这里阐述了。


作为一名程序员,阶段性的学习是必不可少的,而且需要保持一定的持续性,这次在这个阶段内,我对一些重点的知识点进行了系统的复习,一方面巩固了自己的基础,另一方面也提升了自己的知识广度和深度。

用户头像

还未添加个人签名 2022.04.13 加入

还未添加个人简介

评论

发布
暂无评论
JVM基本概念_Java_爱好编程进阶_InfoQ写作平台