JVM
文章平均质量分 77
大将黄猿
一只业余爱好广泛的程序猿!
展开
-
Java8 Lambda表达式的特快处理流Stream快速入门
Stream什么是Stream?Java8最值得学习的特性就是Lambda表达式和Stream API,如果有python或者javascript的语言基础,对理解Lambda表达式有很大帮助,因为Java正在将自己变的更高(Sha)级(Gua),更人性化。--------可以这么说lambda表达式其实就是实现SAM接口的语法糖。Java8中,Collection新增了两个流方法。分别是Stream()和parallelStream()Java8中添加了一个新的接口类Stream,相当于高原创 2021-03-26 15:24:08 · 277 阅读 · 0 评论 -
JVM调优三板斧,快速掌握调优的核心与思路
如何从调优小白走向调优高手说起JVM调优,大伙儿可能瞬间头皮发麻。"好家伙,和调优沾边儿的事儿,不是我这个段位的小新手能解决的"。于是赶紧找来了技术大拿,看大拿三下五除二排查出了问题原因,给出了优化方案。此时,我们的眼里放着光,一脸崇拜的望着大拿,幻想着哪天能成为他这样出色的大佬。这篇文章,就是让你学会调优,掌握一个属于自己的调优节奏与思路。快速了解调优如果你对调优没有什么概念,那么我们先说说调优是什么。所谓调优,就是你的系统生病了。此时,我们就是一个诊所。系统找我们来治治病。我原创 2021-03-17 11:07:27 · 3199 阅读 · 12 评论 -
从Class文件理解Java语言特性,看看Class文件悄悄做了些什么?
我们都知道,程序的执行需要我们先写.java文件,通过javac命令编译成.class文件。但其实class文件在接受到我们的一些逻辑后,悄悄咪咪干了一些不为人知的事儿。今天,我们就来揭开这层神秘面纱。字节码指令---异常处理每个时刻正在执行的当前方法就是虚拟机栈顶的栈帧。方法的执行就对应着栈帧在虚拟机中入栈和出栈的过程。当一个方法执行完,有两种情况,一种是正常执行,另一种是异常。完成出口(返回地址)还记得一个栈帧中的四大天王么?"完成出口"这一部分做了些什么呢?我们站在字节码的角度来看原创 2021-03-03 17:31:09 · 126 阅读 · 2 评论 -
聊聊那些编译器优化
什么是编译器优化在了解了即时编译,提前编译后。大家已经有了一个认知:编译器的目标虽然是做由程序代码翻译为本地机器码的工作,但其实难点并不是能不能由程序代码翻译成机器码,翻译的质量才是决定编译器优秀与否的关键。本节将介绍几种HotSpot虚拟机的即时编译器在生成代码时采用的代码优化技术。以小见大,见微知著,希望大家从这篇文章中对编译器代码优化有一个大概的认知。四种经典编译器优化方法内联(优化陷阱)方法内联的就是把目标方法的代码原封不动的“复制”到发起调用的方法中,避免发生真实的方法调用。它的主原创 2021-02-04 15:32:01 · 636 阅读 · 0 评论 -
如何安全的让所有用户线程Stop The World之使用安全点和安全区域
安全点我们都知道GC在工作过程中,有时不得不进行STW(暂停所有用户线程)。但是要确保用户线程暂停的这行字节码是不会导致引用关系发生变化的。所以JVM会在字节码指令中,选出一些指令作为”安全点”,比如方法调用,循环跳转,异常跳转等,才会产生安全点。为什么叫安全点呢?GC是要暂停业务线程。而业务线程可能是超多线程,他们肯定都要达到自己的Safepoint处才能完成所谓的Stop the world。这里我们有两种方法区实现。1.抢占式中断:当用户线程发现GC需要STW时,直接立刻停下。看看自己是.原创 2021-02-04 10:44:50 · 368 阅读 · 0 评论 -
G1技术细节之记忆集和卡表解决跨代引用问题
跨代引用面临的问题首先,产生跨代引用场景是发生YongGC的过程。此时新生代的对象会开始寻找根,看自己是否属于根可达对象,从而判断自己是否是垃圾。GCRoots在新生代假设现在整个堆空间只有两个对象。此时两个对象都在新生代。此时GC线程是非常容易判断这两个对象被GCRoots引用,属于存活对象。随着程序的长时间运行。此时出现了以下情况:GCRoots移动到老年代可以看到,老年代的对象HumongN被GCRoots所引用,此时HumongN->S就是跨代引用。S又引用着E原创 2021-02-04 10:32:35 · 3324 阅读 · 15 评论 -
与其千篇一律,不如一篇文章彻底搞懂三色标记是如何处理漏标问题
标记清除算法在三色标记之前有一个算法叫标记清除算法。这个算法会设置一个标志位来记录对象是否被使用。最开始所有对象的标记都是0,通过根可达分析算法发现对象存活,就会置为1。一步步执行下去就会呈现出一个类似树状的结构。等标记的步骤完成之后,会将未被标记的对象统一清理,再次把所有的未被回收的标记重置为0,反复执行。这个算法最大的问题是,GC在执行期间需要把整个程序完全暂停,不能异步进行GC操作。因为在不同阶段标记清除算法的标志位0,1具有不同的含义,如果并发处理,则有可能会额外删除新增的存活对象(所有对象原创 2021-02-04 00:05:20 · 1881 阅读 · 3 评论 -
面试高频——JVM内存溢出(OOM)的各种情况
栈溢出HotSpot版本中栈的大小是固定的,不支持扩展。Java.lang.StackOverflowError(单个虚拟机栈)一般普通的方法调用是很难出现的,如果遇到了可能写了无限递归。虚拟机栈带给我们的启示:方法的执行因为要打包成栈帧。所以天生比面向过程的简单循环要慢。所以树的遍历算法中递归和非递归(未封装,直接循环来实现)都有其存在的意义。递归的代码更简洁,非递归代码复制但速度快。栈内存的OOM(此处指的整个运行时数据区的栈空间)的发生条件是:不断地创建线程,JVM会向操作系统不断地申原创 2021-02-02 23:53:55 · 1405 阅读 · 1 评论 -
虚拟机内存优化技术之栈帧之间的数据共享
在一般的模型中。两个不同的栈帧一般是独立的存在,但是大部分JVM 在实现的过程中会进行一些优化,使得两个栈帧出现一部分重叠。(主要体现在方法中有参数传递的情况),让下面栈帧的操作数栈和上面栈帧的部分局部变量重叠在一起。以以下程序为例:此处的调用方的形参x被放入操作数栈,同时,被调用方的局部变量表也共享了此处区域。这样做不但节约了部分空间,更加重要的是在方法调用的时候就可以直接共用一部分数据。无需进行额外的参数辅助传递。...原创 2021-02-02 23:43:02 · 340 阅读 · 1 评论 -
使用JHSDB工具理解分代回收
JHSDB工具是一款基于服务性代理实现的进程外调试工具。服务性代理是HotSpot虚拟机中一组用于映射Java虚拟机运行信息的、主要基于Java语言实现的API集合。(简单来说,是可以在程序运行过程中监控程序状态的一款程序)。启动JHSDB工具保证在JDK的bin目录下也存在sawindbg.dll,没有的话可以从jre目录下面复制一份过来,只要保证两个文件夹都有就行了。JHSDB是我们JDK自带的工具。虽说是自带,但我们依然需要保证..\jdk\bin;..\jdk\jre\bin中包含swi原创 2021-02-02 21:10:44 · 295 阅读 · 0 评论 -
JVM直接内存
什么是直接内存(堆外内存)直接内存有一种叫法,堆外内存。直接内存(堆外内存)指的是Java应用程序通过直接方式从操作系统中申请的内存。这个的差别与之前的堆,栈,方法区不同。那些内存都是经过了虚拟化的内存。哪些代码可以操作直接内存?Unsafe类使用Java的Unsafe类,做一些内地内存的操作。Netty操作直接内存(Direct Memory),底层会调用操作系统的 malloc 函数。JNI和JNA程序有过不同语言间通信经历的一般都知道,它允许Java代码和.原创 2020-12-13 15:31:10 · 653 阅读 · 1 评论 -
玩转MAT—dump与动态分析
前言我们使用jmap-histo这种命令去分析哪些对象占据着我们的堆空间。但是那是比较容易分析的问题。如果遇到的是内存情况比较复杂的情况,基础命令是不容易分析问题的。这时,我们需要借助工具。今天介绍的工具MAT,既可以使用dump日志分析内存问题,也可以在程序运行期间,获取程序当时运行的快照进行分析。内存分析工具JDK自带工具VisualVM案例分析代码本程序可以大概看一下,首先先启动一个线程池。这个线程池的其实容量与最大容量设置死,也就是说最多可同时容纳开启50个线程执行任务。原创 2020-12-08 15:01:18 · 1877 阅读 · 0 评论 -
Arthas快速入门
Arthas (重点)官方文档参考https://alibaba.github.io/arthas/Arthas 是 Alibaba 开源的 Java 诊断工具,深受开发者喜爱。Arthas 支持 JDK 6+,支持 Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断下载和安装 不需要安装,就是一个 jar 包curl -O https://alibaba.github.io/arthas/arthas-boot.原创 2020-12-07 08:59:54 · 1245 阅读 · 0 评论 -
JVM调优思路与分析实战
项目介绍代码介绍本程序可以大概看一下,首先先启动一个线程池。这个线程池的其实容量与最大容量设置死,也就是说最多可同时容纳开启50个线程执行任务。并且队列使用的无界队列。在 Linux 服务跑起来java -cp JVMOTHERS-1.0-SNAPSHOT.jar -XX:+PrintGC -Xms200M -Xmx200M JVM调优/FullGCProblem(把堆空间设置小,提前抛出OOM)。CPU占用过高排查实战1.先通过top命令找到消耗CPU很高的..原创 2020-12-04 17:50:30 · 208 阅读 · 0 评论 -
亿级流量电商系统调优实战
JVM调优分类调优是一个很大的概念,简单的说就是把系统进行优化。(假设代码没有问题的情况下,通过参数配置使程序的往我们期待的情况运行(高吞吐量?低延时?))但是站在一个系统的角度,能够干的事情太多了。我们一般把JVM调优分为以下三类:JVM预调优 优化JVM运行环境(慢,卡顿等) 解决JVM中的问题(OOM)调优中,最明显的是OOM。因为会抛出异常。当然它也只是调优的一部分。预调优和优化运行环境估计很多人的做法都只是服务器重启而已。我们使用AB工具测压(在我的其他博客JVM调优-内存优化有原创 2020-12-04 00:54:28 · 616 阅读 · 0 评论 -
JVM-性能调优——内存优化
JVM 调优是一个系统而又复杂的过程,但我们知道,在大多数情况下,我们基本不用去调整 JVM 内存分配,因为一些初始化的参数已经可以保证应用服务正常稳定地工作了。在应用服务的特定场景下,JVM 内存分配不合理带来的性能表现并不会像内存溢出问题这么突出。一般你没有深入到各项性能指标中去,是很难发现其中隐藏的性能损耗压测工具ABAb(ApacheBench) 测试工具是 Apache 提供的一款测试工具,具有简单易上手的特点,在测试 Web 服务时非常实用。ab 一般都是在 Linux 上用。原创 2020-12-01 01:31:46 · 1095 阅读 · 0 评论 -
JDK自带基础调优工具
JVM调优工具JDK自带工具命令行工具jps(查询进程)列出当前机器上正在运行的虚拟机进程。JPS从操作系统的临时目录上去找(所以有一些信息可能显示不全)-q : 仅仅显示进程-m : 输出主函数传入的参数,下的hello就是在执行程序时从命令行输入的参数-l : 输出应用程序主类完成package名或jar完整名称-v : 列出jvm参数,-Xms20m -Xmx50m是启动程序指定的JVM参数jstat(监控)用于监视虚拟机各种运行状态信息的命令工具。它.原创 2020-11-28 02:50:11 · 574 阅读 · 0 评论 -
Java语法糖以及实现
什么是语法糖?不知道大家有没有经历过,刚学编程时,看到一些java代码会觉得非常别扭。例如编译器使用idea。再用匿名内部类创建一个线程时,程序是这样的。过一阵子重新打开这个文件嗯?这是个啥?于是去找大佬问。大佬:”这就是个语法糖”。”哦~”伴随着一声似懂非懂的声音,心里还在嘀咕着:”语法糖又是个啥?”。可能看到这篇博客的各位都比我当时强,没遇到过我当时出现的问题。但是我还是讲讲我对语法糖的理解。几乎所有的编程语言都会或多或少的提供一下语法糖来方便程序员开发代码。语法..原创 2020-11-24 14:36:42 · 1206 阅读 · 5 评论 -
方法调用的底层实现之虚/非虚方法,动/静态分派
我们写的代码,经过编译,经过类加载的各种阶段,进入了JVM运行时数据区。但作为程序员,我么最关心的是代码的执行,代码的执行其实本质上是方法的执行。站在JVM的角度,归根到底还是字节码的执行,main函数是JVM指令执行的起点。JVM会创建main线程来执行main函数,以触发JVM的一系列指令的执行,真正的把JVM跑起来。接着,在我们的代码中,就是方法调用方法的过程,所以了解方法在JVM中的调用时非常必要的。方法调用的字节码指令关于方法的调用,Java字节码提供了5个指令,来调用不同类型的方法。原创 2020-11-21 18:00:13 · 515 阅读 · 0 评论 -
类加载器的约束——双亲委派,以及打破双亲委派
类加载器整个类加载过程的任务非常繁重,虽然任务中,但是总要有人干。类加载器做的就是上面5个步骤的事。(加载,验证,准备,解析,初始化)。JDK提供的类加载器Bootstrap ClassLoader(启动)这是类加载器中的扛把子,任何类的加载行为,都要经过它。它的作用是加载核心类库,也就是rt.jar.resources.jar,charsets.jar等。当然这些jar包的路径是可以指定的,-Xbootclasspath参数可以完成指定操作。这个加载器是C++编写的,随着JVM启.原创 2020-11-19 10:56:32 · 615 阅读 · 2 评论 -
类加载的七个阶段
一个类的生命周期类生命周期的7个阶段类从被加载到虚拟机内存中开始,到卸载出内存为止。他的整个生命周期包括七个阶段:加载,验证,准备,解析,初始化,使用,卸载7个阶段。其中验证,准备,解析3个部分统称为连接*(Linking)阶段顺序加载,验证,准备,初始化,卸载这五个阶段的顺序是确定的,但是对于”解析”阶段却不一定。它在某些情况下可以再初始化之后再开始,这样做是为了支持java的运行时绑定特性(也称为动态绑定或晚期绑定)加载什么时候需要开始类第一个阶段”加载”呢?虚拟..原创 2020-11-18 00:58:53 · 2463 阅读 · 0 评论 -
从字节码了解Java语言特性,了解字节码做了哪些不为人知的事儿。
字节码指令---异常处理每个时刻正在执行的当前方法就是虚拟机栈顶的栈帧。方法的执行就对应着栈帧在虚拟机中入栈和出栈的过程。当一个方法执行完,有两种情况,一种是正常执行,另一种是异常。完成出口(返回地址)正常返回:(调用程序计数器中的返回地址)三部曲:恢复上层方法的局部变量表和操作数栈 把返回值(如果有的话)压入调用者栈帧的操作数栈中。 调整程序计数器的值指向方法调用指令后面的一条指令。异常返回通过异常处理表中的<非栈帧中的>来确定异常机制...原创 2020-11-17 01:18:56 · 174 阅读 · 0 评论 -
带你一步步认识class文件
JVM的语言无关性与平台无关性是建立在操作系统上,虚拟机厂商提供了许多可以运行在各种不同平台的虚拟机。它们都可以载入和执行字节码,从而实现程序的”一次编写,到处运行”。各种不同平台的虚拟机与平台都统一使用的程序存储格式——字节码(ByteCode)是构成平台无关性的基石,也是语言无关性的基础。Java虚拟机不和包括java在内的任何语言绑定,它只与”Class文件”这种特定的二进制文件格式所关联。Class文件中包含了Java虚拟机指集合符号以及若干其他辅助信息。Class类文件(了解.原创 2020-11-17 01:10:18 · 1358 阅读 · 0 评论 -
解释执行?编译执行?即时编译?轻松让你分清前期编译与后期编译
解释执行与即时编译(JIT)对编译的理解“诶,那个谁谁谁,昨天我把那个bug改好了。你编译一下看看还有那个问题没。”说罢,软件部主任不慌不忙品了一口手中的茶。”主任你太牛逼了!......”。伴随着下属崇拜眼神,主任不禁想起了曾经的自己最开始写代码也是一个连”编译”也不清楚的小白而已。提起编译。我们最最开始的理解便是:程序先把写的代码读一遍,判断一下有没有基本的语法错误。当编译通过之后,就进入了运行模式。那么随着学习的深入与加深理解,对编译的理解已经不能单单局限于此了。在Java技.原创 2020-11-15 17:40:26 · 719 阅读 · 0 评论 -
JVM内存区域以及程序运行时数据在内存中的变化
JVM内存区域JVM运行时数据区原创 2020-11-07 18:24:07 · 548 阅读 · 2 评论 -
从历史了解JVM,以及JVM的学习方向
JVM从编译到执行JAVA 程序执行过程一个Java程序,首先经过编译成.class文件,然后JVM将其加载到方法区。执行引擎会执行这些字节码文件。执行时,会翻译成操作系统相关的函数。JVM作为翻译.class文件的存在。输入字节码,调用操作系统函数。过程:JAVA文件—>编译器—>字节码-->机器码。JVM全称JAVAVirtual Machine,也就是我们常说的JAVA虚拟机。虚拟机只识别class文件,并且可以把class文件解析成机器阅读的机器码...原创 2020-11-08 17:10:25 · 161 阅读 · 0 评论 -
JVM中的对象及引用的那些事儿
JVM中对象的创建流程对象的内存分配当虚拟机遇到一条new指令的时候,首先会检查是否被类加载过了。如果没有先必须执行相应的类加载。类加载就是把class文件加载到JVM运行时数据区的过程。检查加载首先检查这指令的参数是否能在常量池中定位到一个类的符号引用(符号引用:符号引用以一组符号来描述所引用的目标),并且检查类是否已经被加载、解析和初始化过。分配内存接下来虚拟机将为新生对象分配内存。为对象分配空间的任务等同于把一块确定大小的内存从Java堆中划分出来。 指针碰...原创 2020-11-08 19:08:42 · 244 阅读 · 0 评论 -
数据进入运行时数据区的步骤
示例代码如下:步骤说明:JVM向内存申请空间JVM第一步就是通过参数配置或者默认配置参数向操作系统申请内存空间,根据空间大小找到具体的内存分配表,然后把内存段的起始地址和终止地址分配给JVM,接下来JVM再进行内部分配。初始化运行时数据区(分配内存)JVM获取内存空间后,会根据配置参数分配堆,栈以及方法区的内存大小类加载细节后续内容细讲,这里主要是把class放入方法区,还有class中的静态变量,常量也要放入方法区。执行方法并创建对象启动main线程,执行mai..原创 2020-11-08 22:58:12 · 170 阅读 · 2 评论 -
五花缭乱的常量池
堆空间的分代划分堆被划分为新生代和老年代,新生代又被进一步划分为Eden和Survivor区,最后Survivor由From Survivor和To Survivor组成。通过这段代码,实用工具可查看T1对象所在堆的位置与T2对象所在堆的位置不同。(T1经过15次垃圾回收进入了老年代,T2刚刚进入堆内存,处于新生代)。具体使用细节此处不详细讲解。虚拟机内存优化技术栈优化技术-------栈帧之间数据的共享在一般的模型中。两个不同的栈帧一般是独立的存在,但是大部分JVM 在实现..原创 2020-11-09 02:06:00 · 698 阅读 · 0 评论 -
详解分代回收理念,复制算法,标记清除,标记整理算法
垃圾回收概述在内存动态分配和垃圾收集技术语言还在胚胎阶段时,开发者就在思考三个问题。那些内存需要回收?什么时候回收?如何回收?我们讲的运行时数据区主要分为三大类。栈,堆,方法区。栈内存中的程序计数器,虚拟机栈,本地方法栈3个区域随着线程而生,也随线程而灭。每一个栈帧分配的内存基本上在编译期就已经确定下来了。因此这几个区域基本上是具备确定性的,我们不需要在这几个区域考虑垃圾回收问题。当方法结束或线程结束时,内存自然也跟着回收了。而Java堆和方法区则有着明显的不确定性。一个接口所需要的多个实现原创 2020-11-11 01:29:17 · 424 阅读 · 0 评论 -
一步步带你理解CMS与G1垃圾回收器
新生代和老年代垃圾回收算法不同的原因在新生代中。每次垃圾回收都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活的对象的复制成本就可以完成回收。而老年代中因为对象存活率高,没有额外空间对它进行担保,就需要用到"标记——清除"或者"标记整理"算法进行回收。垃圾回收器之间的关系图中上半部分是新生代垃圾回收器,下面是老年代垃圾回收器,连线就是可以搭配使用。没有最好的垃圾回收器,只有最适合的,存在即合理。Serial(串行)/Serial OldJVM刚...原创 2020-11-12 00:53:27 · 1101 阅读 · 0 评论