个人网站设计与制作代码,百度制作的wordpress工具栏,品牌策划方案怎么写,专业做室内设计的网站有哪些JVM学习笔记
复习之前学的内容#xff0c;同时补充以下知识点#xff1a;JVM的双亲委派机制、伊甸区与老年代相关知识#xff1b;
双亲委派机制
双亲的含义应该就是AppClassLoader有#xff1a;ExtClassLoader和BootstrapClassLoader“两个”父加载器。 首先介绍Java中…JVM学习笔记
复习之前学的内容同时补充以下知识点JVM的双亲委派机制、伊甸区与老年代相关知识
双亲委派机制
双亲的含义应该就是AppClassLoader有ExtClassLoader和BootstrapClassLoader“两个”父加载器。 首先介绍Java中的类加载器
Java中的类加载器
Bootstrap ClassLoader启动类加载器默认加载jdk\lib目录下jar中的诸多类。可以使用-Xbootclasspath指定。 Extension ClassLoader扩展类加载器默认加载jdk\lib\ext目录下的jar中的诸多类。可以使用java.ext.dirs系统变量更改。 Application ClassLoader应用程序加载器应用程序加载器负责加载开发人员所编写的诸多类。 User ClassLoader自定义加载器自定义类加载器当存在上述加载器解决不了的特殊情况时或者存在特殊要求时可以自行实现类加载逻辑。 关系图
双亲委派 通俗故事 假设用户刚刚摸鱼时写了个Test类想进行加载此时会发送给应用程序类加载器AppClassLoader然后AppClassLoader并不会直接去加载Test类而是会委派于父类ExtClassLoader来完成此操作ExtClassLoader同样不会直接加载Test类而是会继续委派父类BootstrapClassLoaderBootstrapClassLoader已经是顶层了没有更高的父类加载器了因此BootstrapClassLoader就从jdk\lib中搜索是否存在因为这里是用户自己写的Test类因此不会存在于jdk下所以此时会给子类一个反馈ExtClassLoader收到父类传回的反馈知道父类加载器没有找到对应的类爸爸靠不住就只能自己来加载了结果显而易见自己也不行只能给下面的子类加载器AppClassLoaderAppClassLoader收到父类加载器的反馈顿时明白原来爸爸虽然是爸爸但是终究不能管儿子的私事所以此时AppClassLoader就自己尝试去加载。结果就这样成功了走了一大圈兜兜转转还是自己干。 什么是双亲委派
为什么使用双亲委派
专业性解释①避免类的重复加载②防止核心API被篡改 为了避免原始类被覆盖的问题。 老子走过的路小子不用走 比如用户编写了一个Object类放入程序中加载。 当没有双亲委派机制时就会出现重复的Object类给开发人员造成很大的困扰本来就只需要基于JDK开发就好了现在还得把JDK中的类全记住避免编写重复的类。 当存在双亲委派机制时整个事情就不一样了每次加载类时都会遵循双亲委派机制去问父类是否可以加载如果可以呢那就不需要再次加载了这样事情就简单了。
Tomcat为什么要自定义类加载器 如何打破双亲委派模型太高级尝试看一下
为什么要考虑这个问题
自定义类加载器时重写loadClass方法。
双亲委派还有什么
运行时数据区 蓝色部分是多个线程共享部分 绿色部分为单个线程独享部分
方法区 解释器
JIT编译器
GC
为什么需要GC
垃圾是指JVM中没有任何引用指向的对象如果不清理这些垃圾对象那么他们就一直占用内存而不能给其他对象使用最终垃圾对象越来越多就会出现OOM。
垃圾标记阶段
先找到垃圾对象。
引用计数法
每个对象保存一个引用计数器属性用户记录对象被引用的次数。 a)优点实现简单计数器为0就是垃圾对象 b)缺点 ①无法解决循环引用问题 ②需要额外的空间记录 ③需要额外的时间维护应用计数。
可达性分析方法
以GCRoots作为起始点然后一层一层找到对应的对象被找到的对象就是存活对象那么其他对象就是不可达对象即垃圾对象。 GCRoots包括
线程中虚拟机栈中正在执行的方法中方法参数、局部变量所对应的对象引用线程中本地方法栈中正在执行的方法中方法参数、局部变量所对应的对象引用方法区保存的类对象的静态属性所对应的对象引用方法区保存的类对象的常量属性所对应的对象引用等等
标记清除算法
STWStop The World
标记阶段清除阶段
a) 缺点效率不高产生内存碎片 b) 优点逻辑简单
复制算法
Copying 将内存分为两块每次只使用其中一块进行GC时将可达对象赋值到另外没有被使用的内存块中然后再清楚当前内存块中的所有对象内存块交替使用。 a) 缺点耗费空间较大可达对象多时效率很低因此适用于新生代垃圾对象多的空间对象内存之地变化之后需要额外的时间修改对象的引用地址。 b) 优点没有内存碎片没有标记和清除阶段直接复制操作不需要修改对象头
标记-整理算法
Mark-Compact算法 第一阶段从GCRoots找到并标记可达对象 第二阶段将所有存活对象移动到内存的一端 最后清理边界外所有的空间 a) 缺点需要修改对象引用地址适用于垃圾对象少、可达对象多效率低 三种当中最低的 b) 优点没有内存碎片不需要额外的内存空间
分代收集算法
分代收集的理念 不同对象的存活时间不一样因此可以针对不同的对象采取不同的垃圾回收算法。
新生代的对象存活时间比较短那么就可以利用复制算法它适合对象比较多的情况。老年代的对象存活时间比较长所以不适合用复制算法可以用标记-清除或者标记-整理算法比如 a) CMS垃圾收集器采用的就是标记-清除算法 b) Serial Old采用的就是标记-整理算法
CMS垃圾收集器
整个垃圾收集过程变长了但是STW时间变短了
初始标记STW并发标记重新标记STW时间很短并发清理并发重置 当出现新对象要进入老年代但是空间不够时会导致“concurrent mode failure”此时可以利用Serial Old进行一次垃圾收集就是做一次全局STW。
G1垃圾收集器
Garbage First 将整个内存分为一个个的方块均分为2048块。
初始标记STW并发标记最终标记STW筛选回收STW可以通过-XXMaxGCPauseMillis来制定GC的STW停顿的时间所以可能并不会回收掉所有垃圾对象默认200ms采用复制算法不会产生碎片会把某个region对象复制到另外空闲的region中 YoungGCEden区满了就会触发G1的YoungGC对Eden区进行GC MixedGC老年代占用率达到了-XXInitiatingHeapOccupancyPercent指定的百分比回收所有的新生代以及部分老年代以及大对象区 FullGC在进行MixedGC过程中采用复制算法如果复制过程内存不够会触发FullGC会STW并采用单线程进行标记-整理算法进行GC相当于一次Serial GC
堆区 所有的对象和数组都应该存放在堆区在执行字节码指令时会把创建的对象存入堆中对象对应的引用地址存入虚拟机栈中的栈帧中不过当方法执行完之后刚刚被创建的对象并不会被回收而是要等JVM后台执行GC之后对象才会被回收。
Xms设置堆的初始化内存大小等价于-XXInitialHeapSize;Xmx设置堆的最大内存等价于-XXMaxHeapSize 一般会把两个设置为一样这样JVM就不需要再GC后去修改堆的内存大小了提高了效率默认初始化内存大小物理内存大小/64最大内存大小物理内存大小/4
新生代
可以通过-XXNewRatio参数来配置新生代和老年代的比例默认是2新生代占1老年代占2也就是新生代占堆区的1/3 一般不需要调整只有明确知道存活时间比较长的对象偏多那么就需要调大NewRatio从而调整老年代的占比
Eden伊甸园区新对象都存放在伊甸区除非对象的大小超过了Eden区那么就只能直接进入老年代S0、S1区Survivor0、Survivor1区也可以叫做from区to区用来存放MinorGCYGC后的对象。默认情况下Eden区S0区S1区的比例关系为8:1:1即Eden区占8/10可以用-XXSurvivorRatio调整。 YGCYoung Garbage Collection新生代垃圾回收将Eden区对象放入S0区S0区和S1区交替使用 老年代 当达到某个条件之后剩余对象就会被保存到老年代中。 遇到第二个非常大的对象Eden区原有一个大对象内存不够用时Eden区的大对象会被直接放到老年代S0、S1区放不下 或者来了一个超大对象可以直接放进老年代 GC分类
Young GC/Minor GC负责对新生代进行垃圾回收Old GC/Major GC负责对老年代进行垃圾回收目前只有CMS垃圾收集器会单独对老年代进行垃圾收集其他垃圾收集器基本都是在整堆回收的时候对老年代进行垃圾收集Full GC整堆回收也会堆方法区进行垃圾收集。
程序计数器
记录下一条待执行指令的地址
是物理寄存器的抽象实现用来记录下一条待执行指令的地址它是程序控制流的指示器循环、if else、异常处理、线程恢复等都依赖它来完成解释器工作时就是通过它来获取下一条需要执行的字节码指令的是唯一一个在JVM规范中没有规定任何OutOfMemoryError情况的区域。
Java方法栈
虚拟机栈是线程私有的每个线程创建时都会创建一个虚拟机栈栈内保存一个栈帧一个栈帧就对应一个方法。
虚拟机栈是线程私有的一个方法开始执行栈帧入栈、方法执行完对应的栈帧就出栈所以虚拟机栈不需要进行垃圾回收虚拟机栈存在OutOfMemoryError和StackOverFlowError线程太多就会出现OutOfMemoryError线程创建时没有足够的内存去创建虚拟机栈了方法调用层数过多就会出现StackOverFlowError可以通过-Xss来设置虚拟机栈的大小。
栈帧 操作数栈也可以叫做操作栈是栈帧的一部分操作数栈是用来执行字节码指令过程中用来进行计算的。
操作数栈
比如加法过程运算操作数在计算过程中的进栈出栈
局部变量表
保存局部变量比如加法过程中其实每个变量的值都是保存在局部变量表中的。
方法返回地址
动态链接
本地方法栈
C/C语言写的一些代码 存的是本地方法的栈帧也是线程私有的也会OOM和SOF。