测试轩测试开发必须了解的JVM内存区域划分

【测试轩测试开发必须了解的JVM内存区域划分】
测试轩测试开发必须了解的JVM内存区域划分
本文插图
JVM的重要性
我们知道要运行一个java程序 , 必须要安装jdk或者jre , 这是因为在运行java应用时会先编译成字节码 , 然后通过字节码运行在JVM中 , JVM不仅承担了java字节码的分析和执行 , 同时也内置了自动内存分配管理机制 , 这个机制可以大大降低手动分配回收可能带来的内存泄漏和内存溢出风险 。 JVM内存区域划分
在java中 , 内存区域主要划分为5个区域 , 分别是堆、程序计数器、方法区、虚拟机栈和本地 方法栈
测试轩测试开发必须了解的JVM内存区域划分
本文插图
1、堆
堆是JVM内存中最大的一块内存空间 , 是java内存管理的核心区域 , 同时也是被所有线程共享的 , 用来放置java对象实例 , 几乎所有创建的java对象都是被直接分配在堆上 。 堆内存大小默认为物理内存大小的1/64 , 当然这个值也可以在虚拟机启动的时候通过Xmx参数指定大小 。
2、程序计数器
程序计数器是一块比较小的内存空间 , 在JVM规范中 , 每个线程都有自己的程序计数器 , 并且任何时间一个线程都只有一个方法在运行 。
程序计数器会存储当前线程正在执行的java方法的jvm指令地址 , 我们知道java是多线程语言 , 当执行的线程数量超过CPU核数时 , 这个时候线程会根据时间轮转争夺CPU的资源 , 如果一个线程的时间片用完了或者其他原因导致这个线程要让出CPU , 此时就会需要一个程序计数器来记录下一条要运行的执行比如:分支、循环、异常、线程恢复等都依赖于计数器 。
3、方法区
方法区主要用来存放已被虚拟器加载的类的相关信息 , 包括类信息、运行时常量池、字符串、常量池 , 类的信息又包括了类的版本、字段、方法、接口和父类等信息 , 这也是所有线程共享的一块内存区域 。
JVM在运行一个类的时候 , 要经过加载、链接、初始化三个阶段 , 其中连接阶段又包括验证、准备、解析三个阶段 , 在加载类的时候JVM会先加载class文件 , 在class文件中有类的版本信息、字段、方法和接口、常量池等信息 , 这个常量池主要用于存放编译期间产生的各种字面量和符号引用 。
字面量都有哪些呢:
字符串 , 类似String a = "'v"这种
基本类型的常量 , 也就是被final修饰的基本类型的变量 , 比如 final int a = 9
符号引用都有哪些呢
类、方法的全限定名 , 全限定名就是Java.String.Integer这种形式
字段的名称和描述符以及方法的名称和描述符
类加载到内存以后 。 JVM就会把class文件常量池中的内容存放到运行时的常量池 , 而在解析阶段 , JVM就会把符号引用替换为直接引用 , 也就是对象的引用值 。
4、虚拟机栈
线程在创建的时候 , 同时也会创建一个虚拟机栈 , 用来保存方法的局部变量、操作数栈、动态链接方法和返回地址等信息 , 一个个的栈帧 , 对应着一次次的方法调用 , 在同一时间只会有一个活动的栈帧 , 叫做当前帧 , 方法所在的类就叫做当前类 , 如果该方法中调用了其他方法 , 新的栈帧就会被创建 , 成为新的当前栈帧 , 知道返回结果或者执行结束 , JVM对栈帧只有两个操作 , 压栈和出栈 。
5、本地方法栈
本地方法栈跟 Java 虚拟机栈的功能类似 , 也是每个线程都会创建一个 。 Java 虚拟机栈用于管理 Java 函数的调用 , 而本地方法栈则用于管理本地方法的调用 。 但本地方法并不是用 Java 实现的 , 而是由 C 语言实现的 。 总结
本文主要介绍jvm内存区域划分以及各个区域的主要功能 , 下篇文章我们将介绍jvm的运行原理 , 欢迎关注 , 敬请期待 。


推荐阅读