BTrace

ThreadPoolExecutor 原理解析

泪湿孤枕 提交于 2019-12-02 04:44:59
本文首发于个人微信公众号《andyqian》,期待你的关注 前言 在上一篇文章《 Java线程池ThreadPoolExecutor 》中描述了ThreadPoolExecutor的基本概念,以及一些常用方法。这对于我们来说,是远远不够的,今天就一起来看TreadPoolExecutor类的内部实现。 线程池状态 在学习ThreadPoolExecutor源码时,首先来看看下面这段代码,也是非常重要的一段代码。 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); private static final int COUNT_BITS = Integer.SIZE - 3; private static final int CAPACITY = (1 << COUNT_BITS) - 1; // runState is stored in the high-order bits private static final int RUNNING = -1 << COUNT_BITS; private static final int SHUTDOWN = 0 << COUNT_BITS; private static final int STOP = 1 << COUNT_BITS;

JVM调优(三)——基于Btrace的监控调试

余生颓废 提交于 2019-12-01 16:53:20
JVM调优(三)——基于Btrace的监控调试 简介 Btrace可以动态地向目标应用程序的字节码注入追踪代码 用到的技术: JavaComplierApi、JVMTI、Agent、Instrumentation+ASM Btrace安装入门 通过github搜索进行下载 新建环境变量BTRACE_HOME 添加Path:%BTRACE_HOME%\bin 两种运行脚本的方式 在JVisualVM中添加Btrace插件,添加classpath 使用命令行btracce <pid> Btrace使用详解 ### 拦截方法 普通方法 @OnMethod(clazz="",method="") 构造函数 @OnMethod(clazz="",method="<init>") 拦截同名函数,用参数区分 拦截时机 Kind.ENTRY:入口,默认值 Kind.RETURN:返回 Kind.THROW:异常 Kind.Line:行 拦截this,参数,返回值 this: @Self 入参:可以用AnyType,也可以用真实类型,同名的用真实的 返回:@Return 简单类型:直接获取 复杂类型:反射,类名+属性名 其他 打印行号:Kind.LINE 打印堆栈:Thread.jstack() 打印环境变量 使用注意事项 默认只能本地运行 生产环境可以使用,但是被修改的字节码不会被还原 来源:

利用JVM在线调试工具排查线上问题

孤街浪徒 提交于 2019-12-01 05:42:01
在生产上我们经常会碰到一些不好排查的问题,例如线程安全问题,用最简单的threaddump或者heapdump不好查到问题原因。为了排查这些问题,有时我们会临时加一些日志,比如在一些关键的函数里打印出入参,然后重新打包发布,如果打了日志还是没找到问题,继续加日志,重新打包发布。对于上线流程复杂而且审核比较严的公司,从改代码到上线需要层层的流转,会大大影响问题排查的进度。 这个时候我们可以使用能够在线调试的工具帮助我们查找问题,例如btrace,可以动态的插入代码,极大提高我们查找问题的效率。本文通过生产案例介绍如何用这一类工具快速定位传统方法不好定位的问题。 问题描述 服务器在高并发的情况下cpu消耗很高,响应速度变慢,打threaddump,发现创建了大量的Timer-xxx线程,状态都是runnable,但是没有函数堆栈,也就是刚创建了还没执行。打heapdump看,还是不好发现问题,也只能看到一堆没有堆栈的线程。 查了代码,发现近期改的地方没有主动创建Timer的地方,所以大概率是第三方jar包创建的,怎么才能找到是谁创建的线程。用这种静态的分析方法已经不太好用了,因为不管是ThreadDump还是HeapDump,抓住的都是一个快照,ThreadDump主要用来看线程的状态,HeapDump主要是看内存里的东西,还可以看线程里调用链上的栈的内容(仅限于对象,基本类型看不到)

我的java问题排查工具单

回眸只為那壹抹淺笑 提交于 2019-11-30 12:12:49
原文地址:https://yq.aliyun.com/articles/69520 我的问题排查工具箱 前言 平时的工作中经常碰到很多疑难问题的处理,在解决问题的同时,有一些工具起到了相当大的作用,在此书写下来,一是作为笔记,可以让自己后续忘记了可快速翻阅,二是分享,希望看到此文的同学们可以拿出自己日常觉得帮助很大的工具,大家一起进步。 闲话不多说,开搞。 Linux命令类 tail 最常用的tail -f tail -300f shopbase.log #倒数300行并进入实时监听文件写入模式 grep grep forest f.txt #文件查找 grep forest f.txt cpf.txt #多文件查找 grep 'log' /home/admin -r -n #目录下查找所有符合关键字的文件 cat f.txt | grep -i shopbase grep 'shopbase' /home/admin -r -n --include *.{vm,java} #指定文件后缀 grep 'shopbase' /home/admin -r -n --exclude *.{vm,java} #反匹配 seq 10 | grep 5 -A 3 #上匹配 seq 10 | grep 5 -B 3 #下匹配 seq 10 | grep 5 -C 3 #上下匹配,平时用这个就妥了

线上服务 CPU 100%?一键定位 so easy!

冷暖自知 提交于 2019-11-29 05:01:47
0、背景 经常做后端服务开发的同学,或多或少都遇到过 CPU 负载特别高的问题。尤其是在周末或大半夜,突然群里有人反馈线上机器负载特别高,不熟悉定位流程和思路的同学可能登上服务器一通手忙脚乱,定位过程百转千回。 对此,也有不少同学曾经整理过相关流程或方法论,类似把大象放进冰箱要几步,传统的方案一般是4步: top oder by with P:1040 // 首先按进程负载排序找到 axLoad(pid) top -Hp 进程PID:1073 // 找到相关负载 线程PID printf “0x%x\n”线程PID: 0x431 // 将线程PID转换为 16进制,为后面查找 jstack 日志做准备 jstack 进程PID | vim +/十六进制线程PID - // 例如:jstack 1040|vim +/0x431 - 但是对于线上问题定位来说,分秒必争,上面的 4 步还是太繁琐耗时了,有没有可能封装成为一个工具,在有问题的时候一键定位,秒级找到有问题的代码行呢? 当然可以!工具链的成熟与否不仅体现了一个开发者的运维能力,也体现了开发者的效率意识。 淘宝的oldratlee 同学 就将上面的流程封装为了一个工具: show-busy-java-threads .sh(点击可直接下载,或参考文末链接下载),可以很方便的定位线上的这类问题,下面我会举两个例子来看实际的效果。

Java Attach API

与世无争的帅哥 提交于 2019-11-27 09:19:09
catalog 1. instrucment与Attach API 2. BTrace: VM Attach的两种方式 3. Sun JVM Attach API 1. instrucment与Attach API JDK5中增加了一个包java.lang.instrucment,能够对JVM底层组件进行访问。在JDK 5中,Instrument 要求在运行前利用命令行参数或者系统参数来设置代理类,在实际的运行之中,虚拟机在初始化之时(在绝大多数的 Java 类库被载入之前),instrumentation的设置已经启动,并在虚拟机中设置了回调函数,检测特定类的加载情况,并完成实际工作 ​在Java5中,开发基于Instrucment的应用,需要以下几个步骤 1. 编写premain函数 ​2. jar文件打包 ​3. 运行agent 但是在实际的很多的情况下,我们没有办法在虚拟机启动之时就为其设定代理,这样实际上限制了instrument的应用。而Java SE 6的新特性改变了这种情况,通过Java Tool API中的attach方式,我们可以很方便地在运行过程中动态地设置加载代理类,以达到instrumentation的目的 ​在JDK6中,针对这点做了改进,开发者可以在main开始执行以后,再开启自己的Instrucment程序 Attach

VisualVM:多合一故障处理工具

若如初见. 提交于 2019-11-27 06:05:32
VisualVM(All-in-One Java Troubleshooting Tool)是到目前为止随JDK发布的功能最强大的运行监视和故障处理程序,并且可以遇见在未来一段时间内都是官方主力发展的虚拟机故障处理工具。官方在VisualVM的软件说明中写上了“All-in-One”的描述字样,预示着他除了运行监视、故障处理外,还提供了很多其他方面的功能。如性能分析(Profiling),VisualVM的性能分析功能甚至比起JProfiler、YourKit等专业且收费的Profiling工具都不会逊色多少,而且VisualVM还有一个很大的优点:不需要被监视的程序基于特殊Agent运行,因此他对应用程序的实际性能的影响很小,使得他可以直接应用在生产环境中。这个优点是JProfiler、YourKit等工具无法与之媲美的。 VisualVM兼容范围与插件安装 VisualVM基于NetBeans平台开发,因此他一开始就具备了插件扩展功能的特性,通过插件扩展支持,VisualVM可以做到: 显示虚拟机进程以及进程的配置、环境信息(jps、jinfo)。 监视应用程序的CPU、GC、堆、方法区以及线程的信息(jstat、jstack)。 dump以及分析堆转储快照(jmap、jhat)。 方法级的程序运行性能分析,找到被调用最多、运行时间最长的方法。 离线程序快照

你所不知道的 BigDecimal

流过昼夜 提交于 2019-11-27 03:58:40
本文首发于个人微信公众号《andyqian》, 期待你的关注! 前言 在Java中,我们通常使用 BigDecimal 类型来表示金额,特别是在金融,财务系统中,使用的特别多。例如:转账金额,手续费等等。今天就一起来认识下BigDecimal。 为什么是BigDecimal ? 在此之前,我们先来讲讲为什么要使用 BigDecimal ?而不是Float,Double类型?其实光从表现形式来看,Float,Double,BigDecimal 类型都能表示小数。其区别在于精确计算时,Float 与 Double 类型都会损失精度,当然了,BigDecimal 使用不正确时,也会损失精度。在金融系统中,金额计算是最基本的运算,精度的丢失是绝对不能容忍的。接下来,我们来看看下面的例子: Float 类型: public void testFloat(){ float a = 1.1f; float b = 0.8f; System.out.println("a-b = "+(a-b)); System.out.println("a+b = "+(a+b)); System.out.println("a*b = "+(a*b)); System.out.println("a/b = "+(a/b)); } 结果如下: a-b = 0.3 a+b = 1.9000001 a*b = 0