解读网站建设,海尔网站建设的缺点,十大个人博客网站,为什么建设部网站进不去参考#xff1a;
JVM学习笔记#xff08;一#xff09;_卷心菜不卷Iris的博客-CSDN博客
JVM是运行在操作系统之上的#xff0c;它与硬件没有直接的交互
JVM内存结构#xff1a; 方法区#xff1a;存储已被虚拟机加载的类元数据信息(元空间)
堆#xff1a;存放对象实…参考
JVM学习笔记一_卷心菜不卷Iris的博客-CSDN博客
JVM是运行在操作系统之上的它与硬件没有直接的交互
JVM内存结构 方法区存储已被虚拟机加载的类元数据信息(元空间)
堆存放对象实例几乎所有的对象实例都在这里分配内存
虚拟机栈虚拟机栈描述的是Java方法执行的内存模型每个方法被执行的时候都会同时创建一个栈帧Stack Frame用于存储局部变量表、操作栈、动态链接、方法出口等信息
程序计数器当前线程所执行的字节码的行号指示器
本地方法栈本地方法栈则是为虚拟机使用到的Native方法服务。
执行引擎Execution Engine Execution Engine执行引擎负责解释命令提交操作系统执行。
本地接口Native Interface 本地接口的作用是融合不同的编程语言为 Java 所用它的初衷是融合 C/C程序Java 诞生的时候是 C/C横行的时候要想立足必须有调用 C/C程序于是就在内存中专门开辟了一块区域处理标记为native的代码它的具体做法是 Native Method Stack中登记 native方法在Execution Engine 执行时加载native libraies。
目前该方法使用的越来越少了除非是与硬件有关的应用比如通过Java程序驱动打印机或者Java系统管理生产设备在企业级应用中已经比较少见。因为现在的异构领域间的通信很发达比如可以使用 Socket通信也可以使用Web Service等等不多做介绍。
Native Method Stack 它的具体做法是Native Method Stack中登记native方法在Execution Engine 执行时加载本地方法库。
PC寄存器 每个线程都有一个程序计数器是线程私有的就是一个指针指向方法区中的方法字节码用来存储指向下一条指令的地址即 将要执行的指令代码由执行引擎读取下一条指令是一个非常小的内存空间几乎可以忽略不记。
Method Area方法区 方法区是被所有线程共享所有字段和方法字节码以及一些特殊方法如构造函数接口代码也在此定义。简单说所有定义的方法的信息都保存在该区域此区属于共享区间。
静态变量常量类信息(构造方法/接口定义)运行时常量池存在方法区中但是对象实例存在堆内存中和方法区无关。 stack栈 Stack 栈是什么
栈也叫栈内存主管Java程序的运行是在线程创建时创建它的生命期是跟随线程的生命期线程结束栈内存也就释放对于栈来说不存在垃圾回收问题只要线程一结束该栈就Over生命周期和线程一致是线程私有的。8种基本类型的变量对象的引用变量实例方法都是在函数的栈内存中分配。
栈存储什么?
栈中的数据都是以栈帧Stack Frame的格式存在栈帧是一个内存区块是一个数据集是一个有关方法(Method)和运行期数据的数据集。
栈帧中主要保存3 类数据
本地变量Local Variables输入参数和输出参数以及方法内的变量。
栈操作Operand Stack记录出栈、入栈的操作。
栈帧数据Frame Data包括类文件、方法等等。
栈运行原理
当一个方法A被调用时就产生了一个栈帧 F1并被压入到栈中
A方法又调用了 B方法于是产生栈帧 F2 也被压入栈
B方法又调用了 C方法于是产生栈帧 F3 也被压入栈
……
执行完毕后先弹出F3栈帧再弹出F2栈帧再弹出F1栈帧……
遵循“先进后出”或者“后进先出”原则。 图示在一个栈中有两个栈帧
栈帧 2是最先被调用的方法先入栈
然后方法 2 又调用了方法1栈帧 1处于栈顶的位置
栈帧 2 处于栈底执行完毕后依次弹出栈帧 1和栈帧 2
线程结束栈释放。
每执行一个方法都会产生一个栈帧保存到栈(后进先出)的顶部顶部栈就是当前的方法该方法执行完毕 后会自动将此栈帧出栈。
常见问题栈溢出Exception in thread “main” java.lang.StackOverflowError
通常出现在递归调用时。 堆 堆栈方法区的关系 HotSpot是使用指针的方式来访问对象
Java堆中会存放访问类元数据的地址
reference存储的就是对象的地址
三种JVM
•Sun公司的HotSpot
•BEA公司的JRockit
•IBM公司的J9 VM Heap 堆一个JVM实例只存在一个堆内存堆内存的大小是可以调节的。类加载器读取了类文件后需要把类、方法、常变量放到堆内存中保存所有引用类型的真实信息以方便执行器执行堆内存逻辑上分为三部分
Young Generation Space 新生区 Young/New
Tenure generation space 养老区 Old/Tenure
Permanent Space 永久区 Perm
也称为新生代年轻代、老年代、永久代持久代。 新生区 新生区是对象的诞生、成长、消亡的区域一个对象在这里产生应用最后被垃圾回收器收集结束生命。新生区又分为两部分 伊甸区Eden space和幸存者区Survivor pace 所有的对象都是在伊甸区被new出来的。幸存区有两个 From区Survivor From space和To区Survivor To space。当伊甸园的空间用完时程序又需要创建对象JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC)将伊甸园区中的不再被其他对象所引用的对象进行销毁。然后将伊甸园中的剩余对象移动到幸存 From区。
MinorGC垃圾回收的过程如下
eden、From 复制到 To年龄1 首先当Eden区满的时候会触发第一次GC,把还活着的对象拷贝到Survivor From区当Eden区再次触发GC的时候会扫描Eden区和From区域对这两个区域进行垃圾回收经过这次回收后还存活的对象则直接复制到To区域如果有对象的年龄已经达到了老年的标准则赋值到老年代区同时把这些对象的年龄1
清空 eden、Survivor From 然后清空Eden和From中的对象
To和 From 互换 最后To和From互换原To成为下一次GC时的From区。部分对象会在From和To区域中复制来复制去,如此交换15次(由JVM参数MaxTenuringThreshold决定,这个参数默认是15)最终如果还是存活,就存入到老年代
大对象特殊情况 如果分配的新对象比较大Eden区放不下但Old区可以放下时对象会被直接分配到Old区即没有晋升这一过程直接到老年代了
MinorGC的过程复制 - 清空 - 互换 老年代 经历多次GC仍然存在的对象默认是15次老年代的对象比较稳定不会频繁的GC
若养老区也满了那么这个时候将产生MajorGCFullGC进行养老区的内存清理。若养老区执行了Full GC之后发现依然无法进行对象的保存就会产生OOM异常“OutOfMemoryError”。
如果出现java.lang.OutOfMemoryError: Java heap space异常说明Java虚拟机的堆内存不够。原因有二
1Java虚拟机的堆内存设置不够可以通过参数-Xms、-Xmx来调整。 TODO 具体参数含义
2代码中创建了大量大对象并且长时间不能被垃圾收集器收集存在被引用。
3.1.3. 永久代 永久存储区是一个常驻内存区域用于存放JDK自身所携带的 Class、Interface 的元数据也就是说它存储的是运行环境必须的类信息被装载进此区域的数据是不会被垃圾回收器回收掉的关闭 JVM 才会释放此区域所占用的内存。
对于HotSpot虚拟机很多开发者习惯将方法区称之为“永久代(Parmanent Gen)” 但严格本质上说两者不同或者说使用永久代来实现方法区而已永久代是方法区(相当于是一个接口interface)的一个实现。
实际而言方法区Method Area和堆一样是各个线程共享的内存区域它用于存储虚拟机加载的类信息普通常量静态常量编译器编译后的代码等等虽然JVM规范将方法区描述为堆的一个逻辑部分但它却还有一个别名叫做Non-Heap(非堆)目的就是要和堆分开。
如果出现java.lang.OutOfMemoryError: PermGen space说明是Java虚拟机对永久代Perm内存设置不够。一般出现这种情况都是程序启动需要加载大量的第三方jar包。例如在一个Tomcat下部署了太多的应用。或者大量动态反射生成的类不断被加载最终导致Perm区被占满。
Jdk1.6及之前 有永久代常量池1.6在方法区
Jdk1.7 有永久代但已经逐步“去永久代”常量池1.7在堆
Jdk1.8及之后 无永久代常量池1.8在堆中 永久代与元空间的最大区别之处
永久代使用的是jvm的堆内存但是java8以后的元空间并不在虚拟机中而是使用本机物理内存。因此默认情况下元空间的大小仅受本地内存限制。