简介

Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。

当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决:

  1. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
  2. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
  3. 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
  4. 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
  5. 是否有一个全局视角来查看系统的运行状况?
  6. 有什么办法可以监控到JVM的实时运行状态?
  7. 怎么快速定位应用的热点,生成火焰图?
  8. 怎样直接从JVM内查找某个类的实例?

Arthas支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

安装与下载

Linux

wget https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar --target-ip 0.0.0.0# 选择要监听的java进程
* [1]: 35542[2]: 71560 math-game.jar

Windows

下载链接 --> arthas

下载对应版本zip包解压

打开cmd命令行

cd xxx/xxx/arthas-boot.jar文件夹
java -jar arthas-boot.jar --target-ip 0.0.0.0# 选择要监听的java进程
* [1]: 35542[2]: 71560 math-game.jar

常用命令

文档链接--> api文档

dashboard

当前系统的实时数据面板,按 ctrl+c 退出。

$ dashboard
ID   NAME                           GROUP           PRIORITY   STATE     %CPU      DELTA_TIME TIME      INTERRUPTE DAEMON
-1   C2 CompilerThread0             -               -1         -         1.55      0.077      0:8.684   false      true
53   Timer-for-arthas-dashboard-07b system          5          RUNNABLE  0.08      0.004      0:0.004   false      true
22   scheduling-1                   main            5          TIMED_WAI 0.06      0.003      0:0.287   false      false
-1   C1 CompilerThread0             -               -1         -         0.06      0.003      0:2.171   false      true
-1   VM Periodic Task Thread        -               -1         -         0.03      0.001      0:0.092   false      true
49   arthas-NettyHttpTelnetBootstra system          5          RUNNABLE  0.02      0.001      0:0.156   false      true
16   Catalina-utility-1             main            1          TIMED_WAI 0.0       0.000      0:0.029   false      false
-1   G1 Young RemSet Sampling       -               -1         -         0.0       0.000      0:0.019   false      true
17   Catalina-utility-2             main            1          WAITING   0.0       0.000      0:0.025   false      false
34   http-nio-8080-ClientPoller     main            5          RUNNABLE  0.0       0.000      0:0.016   false      true
23   http-nio-8080-BlockPoller      main            5          RUNNABLE  0.0       0.000      0:0.011   false      true
-1   VM Thread                      -               -1         -         0.0       0.000      0:0.032   false      true
-1   Service Thread                 -               -1         -         0.0       0.000      0:0.006   false      true
-1   GC Thread#5                    -               -1         -         0.0       0.000      0:0.043   false      true
Memory                     used     total    max      usage    GC
heap                       36M      70M      4096M    0.90%    gc.g1_young_generation.count   12
g1_eden_space              6M       18M      -1       33.33%                                  86
g1_old_gen                 30M      50M      4096M    0.74%    gc.g1_old_generation.count     0
g1_survivor_space          491K     2048K    -1       24.01%   gc.g1_old_generation.time(ms)  0
nonheap                    66M      69M      -1       96.56%
codeheap_'non-nmethods'    1M       2M       5M       22.39%
metaspace                  46M      47M      -1       98.01%
Runtime
os.name                                                        Mac OS X
os.version                                                     10.15.4
java.version                                                   15
java.home                                                      /Library/Java/JavaVirtualMachines/jdk-15.jdk/Contents/Home
systemload.average                                             10.68
processors                                                     8
uptime                                                         272s

thread

查看当前线程信息,查看线程的堆栈,可用于查卡顿

参数说明:

参数名称

参数说明

id

线程id

[n:]

指定最忙的前N个线程并打印堆栈

[b]

找出当前阻塞其他线程的线程

[i <value>]

指定cpu使用率统计的采样间隔,单位为毫秒,默认值为200

[--all]

显示所有匹配的线程

$ thread -n 3 # 获取最忙的前三个线程
"C1 CompilerThread0" [Internal] cpuUsage=1.63% deltaTime=3ms time=1170ms"arthas-command-execute" Id=23 cpuUsage=0.11% deltaTime=0ms time=401ms RUNNABLEat java.management@11.0.7/sun.management.ThreadImpl.dumpThreads0(Native Method)at java.management@11.0.7/sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:466)at com.taobao.arthas.core.command.monitor200.ThreadCommand.processTopBusyThreads(ThreadCommand.java:199)at com.taobao.arthas.core.command.monitor200.ThreadCommand.process(ThreadCommand.java:122)at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:82)at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:18)at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:111)at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:108)at com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:385)at java.base@11.0.7/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)at java.base@11.0.7/java.util.concurrent.FutureTask.run(FutureTask.java:264)at java.base@11.0.7/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)at java.base@11.0.7/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)at java.base@11.0.7/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)at java.base@11.0.7/java.lang.Thread.run(Thread.java:834)"VM Periodic Task Thread" [Internal] cpuUsage=0.07% deltaTime=0ms time=584ms

Thread -b, 找出当前阻塞其他线程的线程

有时候我们发现应用卡住了, 通常是由于某个线程拿住了某个锁, 并且其他线程都在等待这把锁造成的。 为了排查这类问题, arthas提供了thread-b, 一键找出那个罪魁祸首。

$ thread -b
"http-bio-8080-exec-4" Id=27 TIMED_WAITINGat java.lang.Thread.sleep(Native Method)at test.arthas.TestThreadBlocking.doGet(TestThreadBlocking.java:22)-  locked java.lang.Object@725be470 <---- but blocks 4 other threads!at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)at test.filter.TestDurexFilter.doFilter(TestDurexFilter.java:46)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)at com.taobao.tomcat.valves.ContextLoadFilterValve$FilterChainAdapter.doFilter(ContextLoadFilterValve.java:191)at com.taobao.eagleeye.EagleEyeFilter.doFilter(EagleEyeFilter.java:81)at com.taobao.tomcat.valves.ContextLoadFilterValve.invoke(ContextLoadFilterValve.java:150)at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:429)at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085)at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)-  locked org.apache.tomcat.util.net.SocketWrapper@7127ee12at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)at java.lang.Thread.run(Thread.java:745)Number of locked synchronizers = 1- java.util.concurrent.ThreadPoolExecutor$Worker@31a6493e

注意, 目前只支持找出synchronized关键字阻塞住的线程, 如果是java.util.concurrent.Lock, 目前还不支持。

jad

反编译指定已加载类的源码,可用于排查线上版本代码是否与本地分支一致

$ jad java.lang.StringClassLoader:Location:/*
* Decompiled with CFR.
*/
package java.lang;import java.io.ObjectStreamField;
import java.io.Serializable;
...public final class Stringimplements Serializable,
Comparable<String>,
CharSequence {private final char[] value;private int hash;private static final long serialVersionUID = -6849794470754667710L;private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();...public String(byte[] byArray, int n, int n2, Charset charset) {/*460*/         if (charset == null) {throw new NullPointerException("charset");}/*462*/         String.checkBounds(byArray, n, n2);/*463*/         this.value = StringCoding.decode(charset, byArray, n, n2);}
...

反编译时只显示源代码

默认情况下,反编译结果里会带有ClassLoader信息,通过--source-only选项,可以只打印源代码。方便和mc/retransform命令结合使用。

$ jad --source-only demo.MathGame
/*
* Decompiled with CFR 0_132.
*/
package demo;import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;public class MathGame {private static Random random = new Random();public int illegalArgumentCount = 0;...

重点命令

watch

函数执行数据观测,可以用于观察方法的入参、返回结果、抛出的异常等信息

让你能方便的观察到指定函数的调用情况。能观察到的范围为:返回值、抛出异常、入参,通过编写 OGNL 表达式进行对应变量的查看。

参数说明

watch 的参数比较多,主要是因为它能在 4 个不同的场景观察对象

参数名称

参数说明

class-pattern

类名表达式匹配

method-pattern

函数名表达式匹配

express

观察表达式,默认值:{params, target, returnObj}

condition-express

条件表达式

[b]

函数调用之前观察

[e]

函数异常之后观察

[s]

函数返回之后观察

[f]

函数结束之后(正常返回和异常返回)观察

[E]

开启正则表达式匹配,默认为通配符匹配

[x:]

指定输出结果的属性遍历深度,默认为 1

这里重点要说明的是观察表达式,观察表达式的构成主要由ognl 表达式组成,所以你可以这样写"{params,returnObj}",只要是一个合法的 ognl 表达式,都能被正常支持。

正常例子

观察函数调用返回时的参数、this对象和返回值

观察表达式,默认值是{params,target,returnObj}

$ watch demo.MathGame primeFactors -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 32 ms, listenerId: 5
method=demo.MathGame.primeFactors location=AtExceptionExit
ts=2021-08-31 15:22:57; [cost=0.220625ms] result=@ArrayList[
@Object[][
@Integer[-179173],
],
@MathGame[
random=@Random[java.util.Random@31cefde0],
illegalArgumentCount=@Integer[44],
],
null,
]
method=demo.MathGame.primeFactors location=AtExit
ts=2021-08-31 15:22:58; [cost=1.020982ms] result=@ArrayList[
@Object[][
@Integer[1],
],
@MathGame[
random=@Random[java.util.Random@31cefde0],
illegalArgumentCount=@Integer[44],
],
@ArrayList[
@Integer[2],
@Integer[2],
@Integer[26947],
],
]
  • 上面的结果里,说明函数被执行了两次,第一次结果是location=AtExceptionExit,说明函数抛出异常了,因此returnObj是null
  • 在第二次结果里是location=AtExit,说明函数正常返回,因此可以看到returnObj结果是一个ArrayList

观察异常信息的例子

$ watch demo.MathGame primeFactors "{params[0],throwExp}" -e -x 2
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 62 ms.
ts=2018-12-03 19:38:00; [cost=1.414993ms] result=@ArrayList[@Integer[-1120397038],java.lang.IllegalArgumentException: number is: -1120397038, need >= 2at demo.MathGame.primeFactors(MathGame.java:46)at demo.MathGame.run(MathGame.java:24)at demo.MathGame.main(MathGame.java:16)
,
]
  • -e表示抛出异常时才触发
  • express中,表示异常信息的变量是throwExp

观察接口超时的例子

按照耗时进行过滤

$ watch demo.MathGame primeFactors '{params, returnObj}' '#cost>200' -x 2
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 66 ms.
ts=2018-12-03 19:40:28; [cost=2112.168897ms] result=@ArrayList[@Object[][@Integer[1],],@ArrayList[@Integer[5],@Integer[428379493],],
]
#cost>200(单
位是ms)表示只有当耗时大于200ms时才会输出,过滤掉执行时间小于200ms的调用

trace

方法内部调用路径,并输出方法路径上的每个节点上耗时

trace 命令能主动搜索 class-pattern/method-pattern 对应的方法调用路径,渲染和统计整个调用链路上的所有性能开销和追踪调用链路。

参数说明

参数名称

参数说明

class-pattern

类名表达式匹配

method-pattern

方法名表达式匹配

condition-express

条件表达式

[E]

开启正则表达式匹配,默认为通配符匹配

[n:]

命令执行次数

#cost

方法执行耗时

这里重点要说明的是观察表达式,观察表达式的构成主要由 ognl 表达式组成,所以你可以这样写"{params,returnObj}",只要是一个合法的 ognl 表达式,都能被正常支持。

正常例子

$ trace demo.MathGame run
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 28 ms.
`---ts=2019-12-04 00:45:08;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69`---[0.617465ms] demo.MathGame:run()`---[0.078946ms] demo.MathGame:primeFactors() #24 [throws Exception]`---ts=2019-12-04 00:45:09;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69`---[1.276874ms] demo.MathGame:run()`---[0.03752ms] demo.MathGame:primeFactors() #24 [throws Exception]

结果里的 #24,表示在run函数里,在源文件的第24行调用了primeFactors()函数。

观察接口超时的例子

$ trace demo.MathGame run '#cost > 1000'
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 41 ms.
`---ts=2018-12-04 01:12:02;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69`---[12.033735ms] demo.MathGame:run()+---[0.006783ms] java.util.Random:nextInt()+---[11.852594ms] demo.MathGame:primeFactors()`---[0.05447ms] demo.MathGame:print()

只会展示耗时大于1000ms的调用路径,有助于在排查问题的时候,只关注异常情况

stack

输出当前方法被调用的调用路径

很多时候我们都知道一个方法被执行,但这个方法被执行的路径非常多,或者你根本就不知道这个方法是从那里被执行了,此时你需要的是 stack 命令。

参数说明

参数名称

参数说明

class-pattern

类名表达式匹配

method-pattern

方法名表达式匹配

condition-express

条件表达式

[E]

开启正则表达式匹配,默认为通配符匹配

[n:]

执行次数限制

这里重点要说明的是观察表达式,观察表达式的构成主要由 ognl 表达式组成,所以你可以这样写"{params,returnObj}",只要是一个合法的 ognl 表达式,都能被正常支持。

正常例子

$ stack demo.MathGame primeFactors
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 36 ms.
ts=2018-12-04 01:32:19;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69@demo.MathGame.run()at demo.MathGame.main(MathGame.java:16)

据条件表达式来过滤

$ stack demo.MathGame primeFactors 'params[0]<0' -n 2
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 30 ms.
ts=2018-12-04 01:34:27;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69@demo.MathGame.run()at demo.MathGame.main(MathGame.java:16)ts=2018-12-04 01:34:30;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69@demo.MathGame.run()at demo.MathGame.main(MathGame.java:16)Command execution times exceed limit: 2, so command will exit. You can set it with -n option.

据执行时间来过滤

$ stack demo.MathGame primeFactors '#cost>5'
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 35 ms.
ts=2018-12-04 01:35:58;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69@demo.MathGame.run()at demo.MathGame.main(MathGame.java:16)

tt

方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测

watch 虽然很方便和灵活,但需要提前想清楚观察表达式的拼写,这对排查问题而言要求太高,因为很多时候我们并不清楚问题出自于何方,只能靠蛛丝马迹进行猜测。

这个时候如果能记录下当时方法调用的所有入参和返回值、抛出的异常会对整个问题的思考与判断非常有帮助。

正常例子

$ tt -t demo.MathGame primeFactors
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 66 ms.INDEX   TIMESTAMP            COST(ms)  IS-RET  IS-EXP   OBJECT         CLASS                          METHOD
-------------------------------------------------------------------------------------------------------------------------------------1000    2018-12-04 11:15:38  1.096236  false   true     0x4b67cf4d     MathGame                       primeFactors1001    2018-12-04 11:15:39  0.191848  false   true     0x4b67cf4d     MathGame                       primeFactors1002    2018-12-04 11:15:40  0.069523  false   true     0x4b67cf4d     MathGame                       primeFactors1003    2018-12-04 11:15:41  0.186073  false   true     0x4b67cf4d     MathGame                       primeFactors1004    2018-12-04 11:15:42  17.76437  true    false    0x4b67cf4d     MathGame                       primeFactors

配合 -i 使用可查看方法参数和异常信息

tt -i index的值

Idea插件

将光标放置在具体的类、字段、方法上面 右键选择需要执行的命令,部分会有窗口弹出、根据界面操作获取命令;部分直接获取命令复制到了剪切板 ,自己启动arthas 后粘贴即可执行。

可以在设置里把这几个打勾,如果不需要可以不勾。

默认情况下,trace不会包含jdk里的函数调用,如果希望trace jdk里的函数,需要显式设置

--skipJDKMethod false

使用Arthas排查问题相关推荐

  1. 当DUBBO遇上Arthas - 排查问题的实践

    Apache Dubbo是Alibaba开源的高性能RPC框架,在国内有非常多的用户. Github: https://github.com/apache/incubator-dubbo 文档:htt ...

  2. 使用 Arthas 排查 SpringBoot 诡异耗时的 Bug

    作者 | 空无 来源 | 阿里巴巴云原生公众号 背景 公司有个渠道系统,专门对接三方渠道使用,没有什么业务逻辑,主要是转换报文和参数校验之类的工作,起着一个承上启下的作用. 最近在优化接口的响应时间, ...

  3. arthas 排查内存溢出_小学妹问我:如何利用可视化工具排查问题?

    有关JVM问题排查的可视化工具有很多,比如说JDK自带的jconsole.jvsualvm等,第三方有MAT.GChisto.GCView等. jconsole查看内存回收情况 jconsole工具在 ...

  4. 使用 Arthas 排查开源 Excel 组件问题

    简介:有了实际的使用之后,不免会想到,Arthas 是如何做到在程序运行时,动态监测我们的代码的呢?带着这样的问题,我们一起来看下 Java Agent 技术实现原理. ​ 背景介绍 ​ 项目中有使用 ...

  5. arthas 排查内存溢出_Java程序线上故障排查

    这篇文章是在公司做了不少的线上Java服务故障排查和优化之后的一个总结,可以作为一个工具清单,在分析问题的时候需要有整体思路:全局观,先从系统层面入手,大致定位方向(内存,cpu,磁盘,网络),然后再 ...

  6. 利用Arthas排查NoSuchMethodError

    1.前言 有时spring boot应用会遇到java.lang.NoSuchMethodError的问题,下面以具体的demo来说明怎样利用arthas来排查. Demo: https://gith ...

  7. 深入Spring Boot:利用Arthas排查NoSuchMethodError

    前言 有时spring boot应用会遇到java.lang.NoSuchMethodError的问题,下面以具体的demo来说明怎样利用arthas来排查. Demo: https://github ...

  8. arthas 排查内存溢出_Java 应用线上问题排查思路、常用工具小结

    前言 本文总结了一些常见的线上应急现象和对应排查步骤和工具.分享的主要目的是想让对线上问题接触少的同学有个预先认知,免得在遇到实际问题时手忙脚乱.毕竟作者自己也是从手忙脚乱时走过来的. 只不过这里先提 ...

  9. 使用Arthas排查解决项目部署后CPU飙高问题

    什么是Arthas Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱. 当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决: 这个类从哪个 jar 包加载的?为什么会报各 ...

最新文章

  1. 陈硕智能指针线程安全_C++ 创建线程的方法
  2. 【数据挖掘知识点五】层次聚类方法的理解
  3. python PyQt5 QtWidgets.QWidget.size()函数 QSize
  4. JVM调优:开启/关闭TLAB和逃逸分析耗时对比
  5. CodeForces - 1301C Ayoub's function(数学)
  6. 理解Python的With语句
  7. 程序| 只要使用这个功能,程序运行速度瞬间提升,高到离谱!
  8. fshc模块fsch2mcu_if理解
  9. Spring或Hibernate其实都提供了透明处理Clob的方法
  10. mysql查询每个表占用空间,【MySQL】查询所有数据库占用磁盘空间大小和单个库中所有表的大小...
  11. 手机运行慢可以刷机吗_为什么手机卡顿,反应变慢怎么解决?一定要刷机吗?...
  12. DisplayTag详解
  13. Squid代理服务器基础_wuli大世界_新浪博客
  14. 麒麟处理器排行天梯图2022 麒麟处理器各型号排行2022
  15. 引用 面向对象 String类(6)
  16. SONY VAIO P VPCP118KJ索尼酷袋本 鸡肋上网本初体验
  17. html随机出现一张图片,图片随机飘动用html怎么做
  18. 2019年 CCPC-Wannafly Winter Camp 总结及感悟
  19. 图1——图的五种存储结构及其初始化
  20. 【论文解析】D2FQ Device-Direct Fair Queueing for NVMe SSDs

热门文章

  1. 【优化布局】matlab基于禁忌搜索算法求解基站选址问题代码
  2. mysql5.7错误提示ERROR 1265 (01000)的问题分析及解决方案和修改字段属性为中文
  3. 关于HTML图片如何设置热区
  4. 51nod 矩阵快速幂模版题
  5. android广告平台介绍
  6. java中定义byte数组,浅谈java的byte数组的不同写法
  7. 透过数据读懂纷繁世界 中译语通“NexMagic再·奇迹”年度峰会召开
  8. iframe、frame、frameset那些事
  9. hutool 获取某月最后一天_Hutool使用指南
  10. 2022大学生寒假社会实践活动稿件怎样向新闻媒体投稿?