什么是 jvm?
jvm 是 jdk 中的一个基础架构, 它的存在主要是运转 java 程序的, 当前在开发当中我们只有真正的去理解 jvm 才能写出高性能的系统, 我们都知道 Windows 与 Linux 系统最终执行的机器码是不一样的, 例如 Windows 中可能是 010101 Linux 中则是 101010 那么我们的 java 系统是可以部署在不同的操作系统之上, 其中 jvm 帮助了我们处理了不同系统的机器码转化, 从而从软件层面解决屏蔽了不同系统的问题, 也就是我们经常说的 java 跨平台
jvm 都分为什么?
1 类加载
2 运行时数据区(本章的内容) 需要掌握的
3 执行子系统
什么是运行时数据区?
运行时数据区就是 jvm 在运转过程中 处理数据的区域, 运行时数据区又分为以下几个区域, 堆, 方法区(元空间),jvm 虚拟栈, 本地方法栈, 程序技数器,
什么是栈呢?(线程私有)
栈是用来保存局部变量的, 栈本身是一种数据结构, 是一个容器, 有着先进后出的特点, 其中我们的栈又包含多个栈桢, 由多个栈桢组成, 每个栈桢相对于我们 java 中的一个方法, 栈桢又可以细分为 局部变量表, 操作数栈, 动态链接, 返回地址, 以下这张图你只要是搞 java 的就一定能看懂,
总结: 局部变量表存储着我们 java8 大基础数据类型对应的字节变量, 在我们开发当中, 要避免栈内存溢出, 例如无限递归循环, 也要避免使用递归处理数据, 因为每执行一次方法 就需要在桢内存开辟新的栈桢空间,
什么是本地方法栈?(线程私有)
本地方法栈是我们 java 借助 C++ 提供的一些特性来完成一些功能, 操作执行步骤与我们的 jvm 的栈是一样的, 这里不做多解释, 比例在 java 中使用 native 来修饰的字段, 其都由本地方法栈来处理,
程序计数器有是什么?(线程私有)
说到程序计数器, 就的先了解字节码文件, 我们的 java 文件编译后的 class 文件, 其中 java 一行代码, 会分解成多行字节码, 每行字节码对应着行号, 我们程序计数器会记录这些行号和对应的地址, 单线程还好, 多线程执行的时候可能会把一个方法分为很多块去执行, 所以需要记录当前执行的行号, 以免下次 get 到 CPU 资源了不知从哪执行,
什么是堆?(公共)
堆里面存放的都是我们创建的对象. 堆分为 新生代区, 老年代区, 为什么堆会分代?
1, 如果没有分代, 所有的对象都在一块, GC 的时要找到哪些对象是没用的, 这样就会对堆的所有区域进行扫描. 而我们的很多对象都是朝生夕死的. 朝生夕死的意思是百分之 90 的对象子创建完不久就会死掉, 如果分代的话, 把新创建的对象放到某一地方, 当 GC 的时先把这块存 "朝生夕死" 对象的区域进行回收, 这样就会腾出很大的空间出来, 以下借助了一张网图 新生区分为 Eden ,From ,To, 在 Eden 存活下来对象会被存放到 From 中 ->To--TenuredSpace 老年代
2,,jvm 给我们提供了几种垃圾回收的处理机制, 各有各的优点, 分代也是为了充分发挥出他们各自的优点, 1 表记性清除法(缺点存在内存碎片)2 表记性清楚整理算法 3 可达性分析算法 3 复制算法,
标记清楚算法: 如果当前对象被引用过一次则对应的标识 + 1 引用失效则对应的标识 - 1 但最终为 0 成为垃圾对象, 清楚之后的空间不会整理, 产生垃圾碎片, 并且两个对象互相引用是检查不出来的
标记清楚整理算法: 与上执行一样 只是对清楚之后的空间进行了整理, 不会有垃圾碎片的存在
可达性分析: gcRoots 把我们的对象引用 链接起来, 被我们的主程序主杆链接的则不是垃圾对象, 否则则是垃圾对象, 有四类称之为 gcRoots 主杆, 1 局部变量引用的对象 2 本地方法栈引用的对象, 3 静态变量引用的对象 4 常量引用的对象 他们被称之为 gcRoots
复制算法: 开辟 2 倍的空间把存货下来的对象 copy 移到新的空间
方法区 (元空间) 又存储着什么?(公共)
java 中的静态变量, 和常量, 是公共的资源,
来源: https://www.cnblogs.com/langjunnan/p/12629502.html