JVM
文章平均质量分 70
花园宝宝胡图图
太菜了
展开
-
简单程序的基本运行流程
public class Test { public static void main(String[] args){ int a = 10; int b = Short.Integer.MAX_VALUE + 1; int c = a + b; System.out.println(c); }}上述代码经由javac之后,编译成.class文件,再由类加载器载入进JVM中。常量池载入运行时常量池即将clas.原创 2022-03-20 19:51:16 · 669 阅读 · 0 评论 -
G1垃圾收集器
同时注重吞吐量和低延迟,默认的暂停目标是200ms 超大堆内存,会将堆划分为多个大小相等的Region G1HeapRegionSize=size ,调整每个Region的大小 整体上是标记 + 整理算法,两个Region之间是复制算法-XX:+UseG1GC JDK9之后默认启用G1收集,JDK9之前若要使用G1收集器需要手动开启Young Collection每个Region都可以独立的作为Eden,幸存者区,老年代。开始的时候,每个格子都是白的,没有创建任何对象,只有..原创 2022-03-15 16:00:22 · 432 阅读 · 0 评论 -
有关JVM的垃圾回收器
1、串行单线程 堆内存较小的时候,适合个人电脑2、吞吐量优先多线程 堆内存较大,多核CPU 我要在单位时间内,占用的stop the world占用的时间最短 0.2 + 0.2 ,虽然时间长,但是发生的次数少3、响应时间优先多线程 堆内存较大,多核CPU 注重垃圾回收的时候,让单次的stop the world的时间尽可能的短 0.1 + 0.1 + 0.1 + 0.1 + 0.1,即发生很多次,但是每次时间都很短串行垃圾回收器-XX:UseSerialGC = Ser原创 2022-03-14 23:15:12 · 672 阅读 · 0 评论 -
关于JVM中GC的一些参数
新生代大小NewSize设置的是初始的新生代大小 MaxNewSize设置的是最大的,-Xmn是一起设置 幸存者比例 默认为8,就是在新生代中占80% FullGC 钱 MinorGC,是否要在Full GC之前触发MinorGC ,默认开启下面是没有任何内存占用的堆内存现创建一个数组,大小7MB出现了一次MinorGC(GC代表的就是MinorGC,Full GC是Full GC),[ DefNew 指的是新生代,回收前 -> 回收后(总大小),垃圾回收消耗的时间 ]...原创 2022-03-14 16:19:55 · 227 阅读 · 0 评论 -
有关Java的分代回收
当我们创建一个对象的时候,首先被放在Eden区,然后不断的创建对象,将Eden区沾满了。当我再要想创建对象的时候,空间已经不够了,就要触发一次Minor GC,将存活的对象,复制到To区,寿命加1,然后清空Eden区,交换From和To区。然后继续分配对象,直到再次满了触发第二次Minor GC,查看幸存者区和Eden区的对象是否能够被垃圾回收,将垃圾回收之后能够存活的对象,放入To区中,同时这些对象的寿命+1,清空垃圾对象,交换To和From区反复多次,直到幸存者区有对象的寿...原创 2022-03-13 22:48:41 · 662 阅读 · 0 评论 -
JVM中的回收算法
标记清除算法将JVM中没有被GC ROOT引用的对象标记 将没有被标记的对象占用的空间进行释放 把对象所占用内存的起始结束地址,放入空闲列表中 速度快,只需要将垃圾对象的内存起始结束地址记录即可,但容易产生内存碎片,清除之后不会再会进一步对内存碎片进行整理了,如果有很多的内存碎片,此时我想插入一个比较大的对象,明明此时我们的内存是充足的,但是地址却不是连续的,这个对象就无法存储了。标记整理算法将JVM中没有被GC ROOT引用的对象标记 将对象删除的同时,将未被删除的对象向前移原创 2022-03-13 21:55:55 · 593 阅读 · 0 评论 -
JVM -- 何为强软弱虚
强引用平常我们使用的引用均为强引用,即new一个对象,通过等号赋值运算符赋值给一个变量,那么这个变量就强引用于新创建的那个对象。只要沿着GC Root对象的引用链能找到这个对象,这个对象就不会被回收软引用只要某个对象没有被强引用直接引用,当垃圾回收时,即使垃圾回收结束了,仍然内存不足,就会将软引用的对象,进行回收。弱引用只要发生了垃圾回收,不管是否内存充足,都会被垃圾回收,即仅仅能存活到下次垃圾回收之前软引用和弱引用还可以配合引用队列工作,如果被软引用引用的对象,被分配到了一个原创 2022-03-13 19:23:58 · 707 阅读 · 0 评论 -
JVM -- StringTable
常量池最初存在于字节码文件中,在运行时被加载到运行时常量池中,其中a,b等就仅仅是常量池中的符号,还未变成Java中的字符串对象。等到执行到引用这个字符串的代码,才会变成字符串对象 。执行 ldc #2 会把 a 符号变为“a”字符串对象执行 ldc #3 会把 b 符号变为“b”字符串对象创建的过程中,会先到StringTable中找,如果有就共用,没有再创建StringTable是一个 HashTable 结构,不能扩容public class StringTableStudy {原创 2022-02-22 19:25:18 · 460 阅读 · 0 评论 -
jvm--堆内存诊断
jps 查看 当前系统中有哪些java 进程使用jmap命令观测上述程序分别检测三次输出后的内存快照jmap -heap 进程id观察到Eden区的被使用内存增大将array=null 后再来观察被使用的内存变少了,说明经过手动调用gc,array被回收了jconsole也可以实现上述的功能,并且利用图形化界面可以连续观察案例:内存回收后,内存占用率依旧很高首先jps查看进程id使用 jmap -heap 进程id...原创 2022-02-20 20:53:43 · 213 阅读 · 0 评论 -
JVM-方法区-方法区的内部机构-03
《深入理解Java虚拟机》书中对方法区(Method Area)存储内容描述如下:它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。 类型信息对每个加载的类型(类class、接口interface、枚举enum、注解annotation),JVm必须在方法区中存储以下类型信息: 这个类型的完整有效名称(全名=包名.类名) 这个类型直接父类的完整有效名(对于interface或是java.lang.object,都没有父类) 这个类型的修饰..原创 2022-01-30 21:55:41 · 72 阅读 · 0 评论 -
JVM-方法区-参数设定与OOM-02
设置方法区大小与OOM方法区的大小不必是固定的,JVM可以根据应用的需要动态调整。jdk7及以前 通过-xx:Permsize来设置永久代初始分配空间。默认值是20.75M -XX:MaxPermsize来设定永久代最大可分配空间。32位机器默认是64M,64位机器模式是82M 当JVM加载的类信息容量超过了这个值,会报异常OutofMemoryError:PermGen space。 JDK8以后元数据区大小可以使用参数 -XX:MetaspaceSize 和原创 2022-01-24 21:12:28 · 863 阅读 · 0 评论 -
JVM-方法区-方法区基本理解-01
方法区从线程共享与否的角度来看栈、堆、方法区的交互关系Person:存放在元空间,也可以说方法区person:存放在Java栈的局部变量表中new Person():存放在Java堆中方法区的理解《Java虚拟机规范》中明确说明:“尽管所有的方法区在逻辑上是属于堆的一部分,但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩。”但对于HotSpotJVM而言,方法区还有一个别名叫做Non-Heap(非堆),目的就是要和堆分开。所以,方法区看作是一块独立于Java堆的内存空间。原创 2022-01-24 17:31:43 · 119 阅读 · 0 评论 -
JVM-堆-逃逸分析-08
堆是分配对象的唯一选择么?---是的逃逸分析在《深入理解Java虚拟机》中关于Java堆内存有这样一段描述:随着JIT编译期的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化,所有的对象都分配到堆上也渐渐变得不那么“绝对”了。在Java虚拟机中,对象是在Java堆中分配内存的,这是一个普遍的常识。但是,有一种特殊情况,那就是如果经过逃逸分析(Escape Analysis)后发现,一个对象并没有逃逸出方法的话,那么就可能被优化成栈上分配。这样就无需在堆上分配内存,原创 2022-01-23 20:30:11 · 131 阅读 · 0 评论 -
JVM-堆-堆空间的参数设置-07
堆空间的参数设置 -XX:+PrintFlagsInitial:查看所有的参数的默认初始值 -XX:+PrintFlagsFinal:查看所有的参数的最终值(可能会存在修改,不再是初始值) -Xms:初始堆空间内存(默认为物理内存的1/64) -Xmx:最大堆空间内存(默认为物理内存的1/4) -Xmn:设置新生代的大小。(初始值及最大值) -XX:NewRatio:配置新生代与老年代在堆结构的占比 -XX:SurvivorRatio:设置新原创 2022-01-23 16:18:39 · 357 阅读 · 0 评论 -
JVM-堆-内存分配策略-06
内存分配策略如果对象在Eden出生并经过第一次Minor GC后仍然存活,并且能被Survivor容纳的话,将被移动到survivor空间中,并将对象年龄设为1。对象在survivor区中每熬过一次MinorGC,年龄就增加1岁,当它的年龄增加到一定程度(默认为15岁,其实每个JVM、每个GC都有所不同)时,就会被晋升到老年代对象晋升老年代的年龄阀值,可以通过选项-xx:MaxTenuringThreshold来设置针对不同年龄段的对象分配原则如下所示: 优先分配到Eden 开发原创 2022-01-23 15:39:02 · 335 阅读 · 0 评论 -
JVM-堆-GC垃圾回收器简略-05
我们都知道,JVM调优的一个环节,也就是垃圾收集,我们需要尽量的避免垃圾回收,因为在垃圾回收的过程中,容易出现STW(Stop the World)的问题,而 Major GC 和 Full GC出现STW的时间,是Minor GC的10倍以上JVM在进行GC时,并非每次都对上面三个内存(新生代、老年代、方法区)区域一起回收的,大部分时候回收的都是指新生代。针对HotSpot VM的实现,它里面的GC按照回收区域又分为两大种类型:一种是部分收集,一种是整堆收集JVM在进行GC时,并非每次都对上面原创 2022-01-23 14:46:37 · 405 阅读 · 0 评论 -
JVM-堆-对象分配过程-04
概念为新对象分配内存是一件非常严谨和复杂的任务,JM的设计者们不仅需要考虑内存如何分配、在哪里分配等问题,并且由于内存分配算法与内存回收算法密切相关,所以还需要考虑GC执行完内存回收后是否会在内存空间中产生内存碎片。 new的对象先放伊甸园区。此区有大小限制。 当伊甸园的空间填满时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(MinorGC),将伊甸园区中的不再被其他对象所引用的对象进行销毁。再加载新的对象放到伊甸园区 然后将伊甸园中的剩余对象移动到幸存者0原创 2022-01-21 17:29:27 · 417 阅读 · 0 评论 -
JVM-堆-新生代与老年代-03
存储在JVM中的Java对象可以被划分为两类: 一类是生命周期较短的瞬时对象,这类对象的创建和消亡都非常迅速 生命周期短的,及时回收即可 另外一类对象的生命周期却非常长,在某些极端的情况下还能够与JVM的生命周期保持一致 Java堆区进一步细分的话,可以划分为年轻代(YoungGen)和老年代(oldGen)其中年轻代又可以划分为Eden空间、Survivor0空间和Survivor1空间(有时也叫做from区、to区)下面这参数开发中一般不会调:.原创 2022-01-21 12:15:55 · 262 阅读 · 0 评论 -
JVM-堆-设置堆内存大小与OOM-02
Java堆区用于存储Java对象实例,那么堆的大小在JVM启动时就已经设定好了,大家可以通过选项"-Xmx"和"-Xms"来进行设置。 “-Xms"用于表示堆区的起始内存,等价于-xx:InitialHeapSize 用来设置(年轻代+老年代)的初始内存大小 -X 是jvm的运行参数 ms 是memory start “-Xmx"则用于表示堆区的最大内存,等价于-XX:MaxHeapSize -Xmx:用来设置(年轻代+老年代)的最大内存大小 .原创 2022-01-21 10:45:56 · 363 阅读 · 0 评论 -
JVM-堆-堆的核心概述-01
一个Java进程对应一个JVM实例 ,一个JVM实例只存在一个堆内存,一个Java进程对应多个线程,线程之间共用一个堆。堆也是Java内存管理的核心区域。Java堆区在JVM启动的时候即被创建,其空间大小也就确定了。是JVM管理的最大一块内存空间。 堆内存的大小是可以调节的。 《Java虚拟机规范》规定,堆可以处于物理上不连续的内存空间中,但在逻辑上它应该被视为连续的。所有的线程共享Java堆,在这里还可以划分线程私有的缓冲区(Thread Local Allocation Buffe原创 2022-01-21 09:59:34 · 80 阅读 · 0 评论 -
JVM-本地方法栈
本地方法栈Java虚拟机栈于管理Java方法的调用,而本地方法栈用于管理本地方法的调用。本地方法栈,也是线程私有的。允许被实现成固定或者是可动态扩展的内存大小。(在内存溢出方面是相同的) 如果线程请求分配的栈容量超过本地方法栈允许的最大容量,Java虚拟机将会抛出一个stackoverflowError 异常。 如果本地方法栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存,或者在创建新的线程时没有足够的内存去创建对应的本地方法栈,那么Java虚拟机将会抛出一个outofM原创 2022-01-20 18:04:30 · 120 阅读 · 0 评论 -
JVM-本地方法接口
什么是本地方法简单地讲,一个Native Methodt是一个Java调用非Java代码的接囗。一个Native Method是这样一个Java方法:该方法的实现由非Java语言实现,比如C。这个特征并非Java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern "c" 告知c++编译器去调用一个c的函数。"A native method is a Java method whose implementation is provided by non-java code."原创 2022-01-20 17:37:31 · 126 阅读 · 0 评论 -
JVM-虚拟机栈-04
方法返回地址存放调用该方法的pc寄存器的值,即存储当前方法调用者被执行到哪行了。一个方法的结束,有两种方式: 正常执行完成 出现未处理的异常,非正常退出 无论通过哪种方式退出,在方法退出后都返回到该方法被调用的位置。方法正常退出时,调用者的pc计数器的值作为返回地址,即调用该方法的指令的下一条指令的地址。而通过异常退出的,返回地址是要通过异常表来确定,栈帧中一般不会保存这部分信息。当一个方法开始执行后,只有两种方式可以退出这个方法:执行引擎遇到任意一个方法返回的字节码指令原创 2022-01-20 15:26:39 · 408 阅读 · 0 评论 -
JVM-虚拟机栈-03
动态链接(或指向运行时常量池的方法引用)动态链接+方法返回地址+附加信息 : 有些地方被称为帧数据区每一个栈帧内部都包含一个指向运行时常量池中该栈帧所属方法的引用包含这个引用的目的就是为了支持当前方法的代码能够实现动态链接(Dynamic Linking)。比如:invokedynamic指令在Java源文件被编译到字节码文件中时,所有的变量和方法引用都作为符号引用(symbolic Reference)保存在class文件的常量池里。比如:描述一个方法调用了另外的其他方法时,就是通原创 2022-01-20 14:48:50 · 609 阅读 · 0 评论 -
JVM-虚拟机栈-02
操作数栈概念操作数栈:Operand Stack每一个独立的栈帧除了包含局部变量表以外,还包含一个后进先出(Last - In - First -Out)的 操作数栈,也可以称之为 表达式栈(Expression Stack)操作数栈,在方法执行过程中,根据字节码指令,往栈中写入数据或提取数据,即 入栈 和 出栈 某些字节码指令将值压入操作数栈,其余的字节码指令将操作数取出栈。使用它们后再把结果压入栈 比如:执行复制、交换、求和等操作 操作数栈,主要用于保存计算.原创 2022-01-19 19:19:32 · 65 阅读 · 0 评论 -
JVM-虚拟机栈-01
虚拟机栈概述由于跨平台性的设计,Java的指令都是根据栈来设计的。不同平台CPU架构不同,所以不能设计为基于寄存器的。优点是跨平台,指令集小,编译器容易实现,缺点是性能下降,实现同样的功能需要更多的指令。首先栈是运行时的单位,而堆是存储的单位 栈解决程序的运行问题,即程序如何执行,或者说如何处理数据。 堆解决的是数据存储的问题,即数据怎么放,放哪里 Java虚拟机栈是什么Java虚拟机栈,早期也叫Java栈。每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(S原创 2022-01-19 17:05:05 · 213 阅读 · 0 评论 -
JVM-程序计数器
JVM中的程序计数寄存器(Program Counter Register)中,Register的命名源于CPU的寄存器,寄存器存储指令相关的现场信息。CPU只有把数据装载到寄存器才能够运行。这里,并非是广义上所指的物理寄存器,或许将其翻译为PC计数器(或指令计数器)会更加贴切(也称为程序钩子),并且也不容易引起一些不必要的误会。JVM中的PC寄存器是对物理PC寄存器的一种抽象模拟。本人更愿意称呼:行号指示器它是一块很小的内存空间,几乎可以忽略不记。也是运行速度最快的存储区域。在JV原创 2022-01-19 11:18:38 · 116 阅读 · 0 评论 -
JVM- 线程
线程是一个程序里的运行单元。JVM允许一个应用有多个线程并行的执行。在Hotspot JVM里,每个线程都与操作系统的本地线程直接映射。 当一个Java线程准备好执行以后,此时一个操作系统的本地线程也同时创建。Java线程执行终止后,本地线程也会回收。 操作系统负责所有线程的安排调度到任何一个可用的CPU上。一旦本地线程初始化成功,它就会调用Java线程中的run()方法。JVM系统线程这些主要的后台系统线程在Hotspot JVM里主要是以下几个: 虚拟机线程:这种线程的操原创 2022-01-19 10:04:45 · 184 阅读 · 0 评论 -
JVM-运行时数据区结构
Java虚拟机定义了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁。另外一些则是与线程一一对应的,这些与线程对应的数据区域会随着线程开始和结束而创建和销毁。灰色的为单独线程私有的,红色的为多个线程共享的。即: 每个线程:独立包括程序计数器、栈、本地栈。 线程间共享:堆、堆外内存(永久代或元空间(方法区)、JIT编译产物的代码缓存) 每个JVM只有一个Runtime实例。即为运行时环境,相当于上图中的那个框框(运行时环境)。..原创 2022-01-19 09:46:49 · 599 阅读 · 0 评论 -
JVM- 如何判断两个class对象是否相同 && 类的主动使用和被动使用
如何判断两个class对象是否相同在JVM中表示两个class对象是否为同一个类存在两个必要条件: 类的完整类名必须一致,包括包名。 加载这个类的ClassLoader(指ClassLoader实例对象)必须相同。 换句话说,在JVM中,即使这两个类对象(class对象)来源同一个Class文件,被同一个虚拟机所加载,但只要加载它们的ClassLoader实例对象不同,那么这两个类对象也是不相等的。JVM必须知道一个类型是由启动加载器加载的还是由用户类加载器加载的。如果一个类型是原创 2022-01-19 09:19:40 · 472 阅读 · 1 评论 -
JVM-双亲委派机制
Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象。而且加载某个类的class文件时,Java虚拟机采用的是双亲委派模式,即把请求交由父类处理,它是一种任务委派模式。工作原理 如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行; 如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器; 如果父类加载器可以完成类加载任原创 2022-01-18 22:27:33 · 67 阅读 · 0 评论 -
JVM-类加载器的分类
JVM支持两种类型的类加载器 。分别为引导类加载器(Bootstrap ClassLoader)和自定义类加载器(User-Defined ClassLoader)。从概念上来讲,自定义类加载器一般指的是程序中由开发人员自定义的一类类加载器,但是Java虚拟机规范却没有这么定义,而是将所有派生于抽象类ClassLoader的类加载器都划分为自定义类加载器,即下图中除了Bootstrap Class Loader都是自定义类加载器。无论类加载器的类型如何划分,在程序中我们最常见的类加载器始终只有3个.原创 2022-01-18 18:12:55 · 107 阅读 · 0 评论 -
JVM-类的加载过程
完整的流程图如下所示第一个环节:加载阶段1、通过一个类的全限定名获取定义此类的二进制字节流2、将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构3、在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口第二个环节:链接阶段验证 Verify目的在于确保Class文件的字节流中包含信息符合当前虚拟机要求,保证被加载类的正确性,不会危害虚拟机自身安全。准备 Prepare为类变量分配内存并且设置该类变量的默...原创 2022-01-18 17:04:01 · 225 阅读 · 0 评论