jdk的内存结构解析(初阶)
jdk大体描述:
jvm虚拟机的设计原理是与操作系统接轨的,主要运行你的代码的也是jvm,jre有很多依赖包,jvm需要这些依赖包运行所以jre叫运行环境包,jdk有很多的工具操作jvm所以jdk叫工具包。他们是互相依赖的关系,不同的系统需要不同的jdk。
jdk运行过程:
jdk通过javac编译java文件为class文件,运行代码不是一个类可以跑的,所以需要Java类库也就是jre,jvm通过类加载器加载class文件,一般通过解释器解释为机器码,通过执行引擎输入到硬件中执行,但还可能走编译器及时编译,像hotspot就是热点数据。
jdk的跨平台性和语言无关性就不在此描述了,无非就是换jdk,jdk有很多版本,但是经过Oracle一顿骚操作都合并的合并收购的收购。到现在1.8已经是很强大的版本了,在此就不赘述强大在什么地方了,后面再详细赘述。
主题开始
jvm的内存区最大分为:运行时数据区,直接内存,直接内存就是我们的电脑内存没有被虚拟机虚拟化的部分,运行时数据区就是被jvm虚拟化的部分。
运行时数据区再分分为:线程私有区,线程共享区,线程私有区是多个线程组成的
线程私有区组成部分是:虚拟机栈,本地方法栈,程序计数器(下面具体说)
线程共享区分为:方法区,堆(以后具体说)
虚拟机栈
虚拟机栈里面是一个一个的栈帧,执行先进后出的原则,一个方法就是一个栈帧,按方法调用的关系来说先压入的方法一定是最后执行完毕,内存的益处就是不断的压入栈栈帧而不释放导致没有足够的空间分配
栈帧里面的区域分为:局部变量表,操作数栈,动态连接,完成出口
栈帧里面的区域解释
局部变量表:存储的内容就是,方法中书写的八大基础类型和对象的引用。new出来的实例会放在堆中间(局部变量表的位置是从0开始的)
操作数栈:操作数栈是一个执行引擎的工作区,同一个操作系统一样,一般的操作系统是cpu+内存+缓存,操作数栈就相当于一个缓存的角色,缓存局部变量表的所正在处理的内容交给执行引擎执行,在返回到局部变量表
完成出口:1.可以理解为一个返回地址,所谓的地址就是在执行class文件时,会有执行顺序,这个顺序可以理解为行号,不是固定的操作就占一个行号,有可能占多个,这里说的行号就是返回地址,这个行号也就是偏移量,c 和c++会说这个,这个Java本身底层也是用c来实现的,这是class字节码的行号或者说偏移,因为一个方法就是一个栈帧,所以这些偏移量是针对这个方法来说的。比如,这行指令对与方法来说的距离为5,这个5就是代表着偏移量了,你对方法的距离有5个偏移量
2.完成出口存的就是栈帧的返回地址,比如这个栈帧的代码要执行完,当他快要执行完的时候,执行到到最后你要返回到哪个地址 ,就比如a方法调用了b方法,此时b方法执行完毕他要返回到a方法的哪个位置。完成出口存的就是这个地址,他存的就是当时a调用b时程序计数器里存的行号
程序计数器
程序计数器:是指向当前线程正在执行的字节码指令的地址(就是记录当前线程正在执行的代码偏移量是多少),他是一块很小的内存,他只是记录当前正线程在执行的字节码指令地址,所以不存在内存溢出的问题,也是jvm内存中唯一不会内存溢出的地方。为什么要有程序技术器,最重要的是因为cpu轮转
本地方法栈
本地方法栈:运行的是本地方法,不是java方法。意味着他不是java里面实现的,用的是c或者是c++。java方法指的就是你的自己写的代码放到jvm执行时会在虚拟机栈中执行,用本地方法栈执行一些写好的工具代码帮你获取数据然后返回给你使用,比如查看底层代码时被native修饰的方法就是调用的本地方法,在本地方法栈中执行,(这个原因是因为,早期Java还是弱鸡的时候只能借助c、c++ 的代码来操作,来兼容c、c++,就有了这个东西),单独划出一块单开个本地方法栈的原因是因为着虚拟机规范,规定着执行外部的东西就要用本地方法栈,要和虚拟机栈分开
所以虚拟机栈存储的是,当前线程运行方法所需的,数据,指令,返回地址。
方法区
方法区:当你jvm刚跑起来,你还没有任何的操作的时候,你的方法区和堆已经就划好了,方法区就是加载相关类的地区,就是你的代码需要很多jar包支持,方法区就是加载这些jar包的,包括静态变量,还有常量,运行时常量池都加载在方法区,1.8的元空间指的就是方法区的实现,之前的叫永久代,他们都是方法区的实现,方法区首先会类加载,把class文件放进去,class文件要经过解析,他在解析class的时候会把一些数据放到常量池里去,这个常量池会分为运行时常量池,和静态常量池,静态常量池就是本身定义在class里面的常常量池,这个叫静态常量池,,运行时常量池是,当class加载到方法区的时候,还会做一个事情,把符号应用替换为直接引用,就是比如说,Tab.add();这种东西替换为内存地址,内存地址就是直接引用,像调用方法之类的都是符号引用。
堆:我们的对象都放在堆里面的

浙公网安备 33010602011771号