Java 诊断工具 Arthas 常见命令

基本概念

云原生这么多微服务,当然需要一个诊断利器来排查问题。

Arthas 是阿里开源的 Java 诊断工具,深受开发者喜爱。在线排查问题,无需重启;动态跟踪 Java 代码;实时监控 JVM 状态。Arthas 支持 JDK 6+,支持 Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

官方定义为Java应用诊断利器,截至目前github收获30.2K个star。

可以用来查看线程,内存,GC和运行时状态,查看入参/返回值/异常,快速定位应用的热点,生成火焰图等功能,帮助更快排查疑难问题。本文主要讲述常见命令的使用。

常见命令

启动arthas-demo(案例程序)

执行如下命令下载 arthas-demo.jar,再用java -jar命令启动案例程序:

wget https://arthas.aliyun.com/arthas-demo.jar;
java -jar arthas-demo.jar

启动arthas-boot(诊断工具程序)

执行如下命令下载arthas-boot.jar,再用java -jar命令启动:

wget https://arthas.aliyun.com/arthas-boot.jar;
java -jar arthas-boot.jar

arthas-boot是Arthas的启动程序,它启动后,会列出所有的Java进程,用户可以选择需要诊断的目标进程。

选择要诊断的Java程序,我这里输入 1 ,再按回车键(Enter)。

Attach成功之后,会打印Arthas LOGO。

输入 help 可以获取到Arthas相关命令帮助信息。

[arthas@1266]$ helpNAME         DESCRIPTION                                                                             help         Display Arthas Help                                                                     auth         Authenticates the current session                                                       keymap       Display all the available keymap for the specified connection.                          sc           Search all the classes loaded by JVM                                                    sm           Search the method of classes loaded by JVM                                              classloader  Show classloader info                                                                   jad          Decompile class                                                                         getstatic    Show the static field of a class                                                        monitor      Monitor method execution statistics, e.g. total/success/failure count, average rt, fail rate, etc.                                                                             stack        Display the stack trace for the specified class and method                              thread       Display thread info, thread stack                                                       trace        Trace the execution time of specified method invocation.                                watch        Display the input/output parameter, return object, and thrown exception of specified me thod invocation                                                                         tt           Time Tunnel                                                                             jvm          Display the target JVM information                                                      memory       Display jvm memory info.                                                                perfcounter  Display the perf counter information.                                                   ognl         Execute ognl expression.                                                                mc           Memory compiler, compiles java files into bytecode and class files in memory.           redefine     Redefine classes. @see Instrumentation#redefineClasses(ClassDefinition...)              retransform  Retransform classes. @see Instrumentation#retransformClasses(Class...)                  dashboard    Overview of target jvm's thread, memory, gc, vm, tomcat info.                           dump         Dump class byte array from JVM                                                          heapdump     Heap dump                                                                               options      View and change various Arthas options                                                  cls          Clear the screen                                                                        reset        Reset all the enhanced classes                                                          version      Display Arthas version                                                                  session      Display current session information                                                     sysprop      Display, and change the system properties.                                              sysenv       Display the system env.                                                                 vmoption     Display, and update the vm diagnostic options.                                          logger       Print logger info, and update the logger level                                          history      Display command history                                                                 cat          Concatenate and print files                                                             base64       Encode and decode using Base64 representation                                           echo         write arguments to the standard output                                                  pwd          Return working directory name                                                           mbean        Display the mbean information                                                           grep         grep command for pipes.                                                                 tee          tee command for pipes.                                                                  profiler     Async Profiler. https://github.com/jvm-profiling-tools/async-profiler                   vmtool       jvm tool                                                                                stop         Stop/Shutdown Arthas server and exit the console.   

与linux同样规则的命令此处不再赘述。如:history,cat,echo,pwd,grep。

系统的实时数据面板 dashboard 命令

dashboard 命令可以查看当前系统的实时数据面板。可以查看到CPU、内存、GC、运行环境等信息。

输入 q 或者 Ctrl+C 可以退出dashboard命令。

打印线程ID 的栈 thread

thread 1 命令会打印线程ID 1的栈。用 thread 1 | grep 'main(' 查找到main class。

查找JVM里已加载的类 sc/sm

可以通过 sc 命令来查找JVM里已加载的类,通过-d参数,可以打印出类加载的具体信息,很方便查找类加载问题。

[arthas@1266]$ sc -d *MathGameclass-info        demo.MathGame                                                                                             code-source       /home/shell/arthas-demo.jar                                                                               name              demo.MathGame                                                                                             isInterface       false                                                                                                     isAnnotation      false                                                                                                     isEnum            false                                                                                                     isAnonymousClass  false                                                                                                     isArray           false                                                                                                     isLocalClass      false                                                                                                     isMemberClass     false                                                                                                     isPrimitive       false                                                                                                     isSynthetic       false                                                                                                     simple-name       MathGame                                                                                                  modifier          public                                                                                                    annotation                                                                                                                  interfaces                                                                                                                  super-class       +-java.lang.Object                                                                                        class-loader      +-sun.misc.Launcher$AppClassLoader@1b6d3586                                                               +-sun.misc.Launcher$ExtClassLoader@107df6e5                                                             classLoaderHash   1b6d3586                                                                                                  Affect(row-cnt:1) cost in 50 ms.

sc支持通配,比如搜索所有的StringUtils:

sc *StringUtils

查找UserController的ClassLoader

[arthas@1266]$ sc -d com.example.demo.arthas.user.UserController | grep classLoaderHashclassLoaderHash   19469ea2

sm命令则是查找类的具体函数。比如:

sm java.math.RoundingMode

通过-d参数可以打印函数的具体属性:

sm -d java.math.RoundingMode

查找特定的函数,比如查找构造函数:

sm java.math.RoundingMode <init>

反编译代码 jad命令

jad demo.MathGame

通过--source-only参数可以只打印出在反编译的源代码:

jad --source-only com.example.demo.arthas.user.UserController

动态执行代码 ognl 命令

在Arthas里,有一个单独的ognl命令,可以动态执行代码。这个有点秀啊😯😯😯

调用static函数

ognl '@java.lang.System@out.println("hello ognl")'

获取静态类的静态字段

获取UserController类里的logger字段:

ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader @com.example.demo.arthas.user.UserController@logger

通过-x参数控制返回值的展开层数。比如:

ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -x 2 @com.example.demo.arthas.user.UserController@logger

执行多行表达式,赋值给临时变量,返回一个List

ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}'
  • OGNL特殊用法请参考:https://github.com/alibaba/arthas/issues/71

  • OGNL表达式官方指南:https://commons.apache.org/proper/commons-ognl/language-guide.html

查看函数的参数/返回值/异常信息 watch 命令

watch demo.MathGame primeFactors returnObj

查看JVM信息 sysprop sysenv jvm dashboard

sysprop

  • sysprop :打印所有的System Properties信息。

  • 指定单个key:sysprop user.dir

  • 通过grep过滤 :sysprop | grep user

  • 设置新的value:sysprop testKey testValue

sysenv

sysenv 命令可以获取到环境变量。和sysprop命令类似。

jvm

jvm 命令会打印出JVM的各种详细信息。

dashboard

dashboard 命令可以查看当前系统的实时数据面板。

重置增强类 reset 命令

通过reset命令可以重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类。Arthas在 watch/trace 等命令时,实际上是修改了应用的字节码,插入增强的代码。显式执行 reset 命令,可以清除掉这些增强代码。

reset 还原指定类:

reset demo.MathGame

还原所有增强类:

reset

查看当前会话信息 session

tee 命令

类似传统的tee命令 用于读取标准输入的数据,并将其内容输出成文件。

tee指令会从标准输入设备读取数据,将其内容输出到标准输出设备,同时保存成文件。

查看当前Arthas版本 version

[arthas@1710]$ version
3.6.2

退出Arthas

输入 exit 或者 quit 命令可以退出Arthas当前session。执行 stop 命令彻底退出Arthas。

📌PS:所有命令都可以通过 -h 参数查看帮助信息。

实操案例

排查函数调用异常

通过curl 请求接口只能看到返回异常,但是看不到具体的请求参数和堆栈信息。

shell@Alicloud:~$ curl http://localhost:61000/user/0
{"timestamp":1655435063042,"status":500,"error":"Internal Server Error","exception":"java.lang.IllegalArgumentException","message":"id < 1","path":"/user/0"}

查看UserController的 参数/异常

在Arthas里执行:

watch com.example.demo.arthas.user.UserController * '{params, throwExp}'
  • 第一个参数是类名,支持通配

  • 第二个参数是函数名,支持通配 访问 curl http://localhost:61000/user/0,watch命令会打印调用的参数和异常

再次通过curl 调用可以在arthas里面查看到具体的异常信息。

把获取到的结果展开,可以用-x参数:

watch com.example.demo.arthas.user.UserController * '{params, throwExp}' -x 2

返回值表达式

在上面的例子里,第三个参数是返回值表达式,它实际上是一个ognl表达式,它支持一些内置对象:

  • loader

  • clazz

  • method

  • target

  • params

  • returnObj

  • throwExp

  • isBefore

  • isThrow

  • isReturn

比如返回一个数组:

watch com.example.demo.arthas.user.UserController * '{params[0], target, returnObj}'

条件表达式

watch命令支持在第4个参数里写条件表达式,比如:

  • 当访问 user/1 时,watch命令没有输出

  • 当访问 user/101 时,watch会打印出结果。

当异常时捕获

watch命令支持-e选项,表示只捕获抛出异常时的请求:

watch com.example.demo.arthas.user.UserController * "{params[0],throwExp}" -e

按照耗时进行过滤

watch命令支持按请求耗时进行过滤,比如:

watch com.example.demo.arthas.user.UserController * '{params, returnObj}' '#cost>200'

热更新代码

这个也是真的秀。

访问 http://localhost:61000/user/0 ,会返回500异常:

shell@Alicloud:~$ curl http://localhost:61000/user/0
{"timestamp":1655436218020,"status":500,"error":"Internal Server Error","exception":"java.lang.IllegalArgumentException","message":"id < 1","path":"/user/0"}

通过热更新代码,修改这个逻辑。

jad反编译UserController

jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java

jad反编译的结果保存在 /tmp/UserController.java文件里了。

再打开一个Terminal 窗口,然后用vim来编辑/tmp/UserController.java

vim /tmp/UserController.java

比如当 user id 小于1时,也正常返回,不抛出异常:

@GetMapping(value={"/user/{id}"})
public User findUserById(@PathVariable Integer id) {logger.info("id: {}", (Object)id);if (id != null && id < 1) {return new User(id, "name" + id);// throw new IllegalArgumentException("id < 1");}return new User(id.intValue(), "name" + id);
}

sc查找加载UserController的ClassLoader

[arthas@1266]$ sc -d *UserController | grep classLoaderHashclassLoaderHash   19469ea2

classLoaderHash 是19469ea2,后面需要使用它。

mc

保存好/tmp/UserController.java之后,使用mc(Memory Compiler)命令来编译,并且通过-c或者–classLoaderClass参数指定ClassLoader

mc --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader /tmp/UserController.java -d /tmp
[arthas@1266]$ mc --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader /tmp/UserController.java -d /tmp
Memory compiler output:
/tmp/com/example/demo/arthas/user/UserController.class
Affect(row-cnt:1) cost in 2879 ms.

也可以通过mc -c /tmp/UserController.java -d /tmp,使用-c参数指定ClassLoaderHash:

mc -c 19469ea2 /tmp/UserController.java -d /tmp

redefine

再使用redefine命令重新加载新编译好的UserController.class

[arthas@1266]$ redefine /tmp/com/example/demo/arthas/user/UserController.class
redefine success, size: 1, classes:
com.example.demo.arthas.user.UserController

热修改代码结果

redefine成功之后,再次访问 user/0 ,结果正常

shell@Alicloud:~$ curl http://localhost:61000/user/0
{"id":0,"name":"name0"}

动态更新应用Logger Level

查找UserController的ClassLoader

[arthas@1266]$ sc -d *UserController | grep classLoaderHashclassLoaderHash   19469ea2

用ognl获取logger

ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader ‘@com.example.demo.arthas.user.UserController@logger’
[arthas@1266]$ ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'
@Logger[serialVersionUID=@Long[5454405123156820674],FQCN=@String[ch.qos.logback.classic.Logger],name=@String[com.example.demo.arthas.user.UserController],level=null,effectiveLevelInt=@Integer[20000],parent=@Logger[Logger[com.example.demo.arthas.user]],childrenList=null,aai=null,additive=@Boolean[true],loggerContext=@LoggerContext[ch.qos.logback.classic.LoggerContext[default]],
]

可以知道UserController@logger实际使用的是logback。可以看到level=null,则说明实际最终的level是从root logger里来的。

单独设置UserController的logger level

ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger.setLevel(@ch.qos.logback.classic.Level@DEBUG)'

再次获取UserController@logger,可以发现已经是DEBUG了。

修改logback的全局logger level

通过获取root logger,可以修改全局的logger level

ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@org.slf4j.LoggerFactory@getLogger("root").setLevel(@ch.qos.logback.classic.Level@DEBUG)'

获取Spring Context,在获取 bean,再调用函数

使用tt命令获取到spring context

tt即 TimeTunnel,它可以记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测。

官方tt说明:https://arthas.aliyun.com/doc/tt.html

tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod

访问user/1:

 curl http://localhost:61000/user/1

可以看到tt命令捕获到了一个请求:

输入 q 或者 Ctrl + C 退出上面的 tt -t命令。

使用tt命令从调用记录里获取到spring context

tt -i 1000 -w 'target.getApplicationContext()'

获取spring bean,并调用函数

tt -i 1000 -w ‘target.getApplicationContext().getBean(“helloWorldService”).getHelloMessage()’

结果如下:

[arthas@1266]$ tt -i 1000 -w 'target.getApplicationContext().getBean("helloWorldService").getHelloMessage()'
@String[Hello World]
Affect(row-cnt:1) cost in 1 ms.

排查HTTP请求返回401

请求接口没有权限的时候一般就返回401 Unauthorized。

401通常是被权限管理的Filter拦截了,那么到底是哪个Filter处理了这个请求,返回了401?

跟踪所有的Filter函数

开始trace:

trace javax.servlet.Filter *

可以在调用树的最深层,找到AdminFilterConfig$AdminFilter返回了401

+---[3.806273ms] javax.servlet.FilterChain:doFilter()
|   `---[3.447472ms] com.example.demo.arthas.AdminFilterConfig$AdminFilter:doFilter()
|       `---[0.17259ms] javax.servlet.http.HttpServletResponse:sendError()

通过stack获取调用栈

上面是通过trace命令来获取信息,从结果里,我们可以知道通过stack跟踪HttpServletResponse:sendError(),同样可以知道是哪个Filter返回了401

执行:

stack javax.servlet.http.HttpServletResponse sendError 'params[0]==401'

访问可以看到如下堆栈信息:

查找Top N线程

查看所有线程信息

thread

查看具体线程的栈

查看线程ID 2的栈:

thread 2

查看CPU使用率top n线程的栈

thread -n 3

查看5秒内的CPU使用率top n线程栈

thread -n 3 -i 5000

查找线程是否有阻塞

thread -b

更多使用查看:

  • Github地址: https://github.com/alibaba/arthas

  • 文档地址: https://arthas.aliyun.com/doc/

转自:blog.csdn.net/qq_35427589/article/details/125331696

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/443264.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

28和lba48命令格式区别_编译Sass(命令行)

本文作者&#xff1a;开课吧无忧图文编辑&#xff1a;开三金sass编译有很多种方式&#xff0c;如命令行编译模式、编辑器自动编译、编译软件koala、sass-loader等。今天我们就先来看第一种&#xff1a;命令行编译刚才我在test文件夹里面已经建立了一个style.scss文件&#xff0…

子窗体中组合框联动_一张表实现组合框联动

嗨&#xff0c;大家中午好&#xff01;最近&#xff0c;有网友给我私信&#xff0c;想要一个联动的示例&#xff0c;一个有关于部门联动的操作。其实关于联动的操作有很多&#xff0c;可以是组合框的联动&#xff0c;列表框联动&#xff0c;组合框与列表框也可以联动&#xff0…

中如何实现文字转语音_录音转文字、文字转语音,学会这一招就够了!手把手教你如何操作...

阅读文章时候想着有人可以把文章读给我听就好了&#xff0c;写作时想着语音直接可以转换成文字就好了&#xff0c;大家是不是有时会突然冒出这样的想法&#xff1f;七十这些看似天真的想法&#xff0c;还真的有办法解决&#xff0c;这里就手把手教你如何操作才能将的文字转换成…

图像 理想低通滤波_图像处理之滤波(下)

[toc]目录一、常规滤波低通高通带通带阻二、非局部均值滤波三、维纳滤波四、卡尔曼滤波前言所谓滤波&#xff0c;其实就是从混合在一起的诸多信号中提取出所需要的信号。信号的分类&#xff1a;确定型信号&#xff0c;可以表示为确定的时间函数&#xff0c;可确定其在任何时刻的…

泰山行宫碧霞元君祠_临清市泰山行宫碧霞元君祠5月4号(农历三月三十日)举行大型泰山奶奶接驾法会...

临清是泰山奶奶的娘家&#xff0c;每年的四月泰山奶奶要回临清省亲临清市道教协会定于2019年农历三月三十(5月4号星期六)于临清桑树园泰山行宫碧霞元君祠举行大型泰山奶奶迎鸾接驾庙会。届时&#xff0c;将有架鼓会、云龙会、狮胞会、钢叉会、高跷会、天音会、彩船会、秧歌会等…

充分条件反过来是必要条件吗_“充分必要条件”引发的现实思考

昨天看了一篇文章是介绍“充分条件和必要条件”&#xff0c;大致就是A能直接推导出B&#xff0c;那A就是B的充分条件。A不一定能推导出B&#xff0c;但是没A一定推导不出B&#xff0c;那A就是B必要条件。举个简单的例子&#xff1a;对你好&#xff08;A&#xff09;与喜欢你&am…

手机游戏降低游戏延迟的软件_怎么降低手机网络延迟(减少网络延迟的5个小技巧)...

在过去的几十年里&#xff0c;用户或开发人员并不担心延迟。在上世纪90年代和本世纪初&#xff0c;个人互联网连接速度要慢得多&#xff0c;因此发送请求和接收响应之间的延迟要远远小于下载完成所需的时间。如今&#xff0c;更高的带宽连接使下载速度更快&#xff0c;因此延迟…

mysql极客_极客mysql16

1.MySQL会为每个线程分配一个内存(sort_buffer)用于排序该内存大小为sort_buffer_size1>如果排序的数据量小于sort_buffer_size&#xff0c;排序将会在内存中完成2>如果排序数据量很大&#xff0c;内存中无法存下这么多数据&#xff0c;则会使用磁盘临时文件来辅助排序&a…

linux 测试环境启用jar_Linux下搭建测试环境

一、下载安装包https://pan.baidu.com/s/1h-Nk8HcWKKtqbjrn0J_t1g 457jJDK1.8安装包、Tomcat8安装包本文用的远程连接Linux操作系统的客户端工具为Xshell&#xff0c;相关使用请自行百度二、安装JDK1、先检查该环境是否已经安装过jdk。输入java -version。如果有&#xff0c;…

代码中 密码存储_你还记得浏览器自动存储的密码吗?用js代码恢复一下记忆吧...

哈喽大家好我是无知便是罪专注于收集和分享互联网上不为人知的好东西正常来说我们的手机和浏览器都有一个非常实用的功能就是可以自动的加密存储我们的常用密码了然后呢在我们需要的时候呢它可以自动填入进来非常非常的省时省力不过呢这种功能的我们用久了就很容易忘记自己当初…

diff算法阮一峰_【重学数据结构与算法(JS)】字符串匹配算法(三)——BM算法

前言文章的一开头&#xff0c;还是要强调下字符串匹配的思路将模式串和主串进行比较从前往后比较从后往前比较2. 匹配时&#xff0c;比较主串和模式串的下一个位置3. 失配时,在模式串中寻找一个合适的位置如果找到&#xff0c;从这个位置开始与主串当前失配位置进行比较如果未找…

python input 拖入路径 去除转义 空格_python学习笔记(基础-2)(转载)

1.输出用print()在括号中加上字符串&#xff0c;就可以向屏幕上输出指定的文字。2.输入如果要让用户从电脑输入一些字符怎么办&#xff1f;Python提供了一个input()&#xff0c;可以让用户输入字符串&#xff0c;并存放到一个变量里。输入是Input&#xff0c;输出是Output&…

mysql和mdy_Liunx下安装MySql

1.安装数据库&#xff1a;执行命令 yum -y install mysql-server2.启动数据库&#xff1a;安装完毕&#xff0c;执行命令service mysqld start3.登录数据库&#xff1a;mysql -u root -p回车后输入密码(mysql的默认用户名是root&#xff0c;密码为空)4.使用数据库&#xff1a;登…

python websocket服务器https_Socket与WebSocket以及http与https重新总结

Socket与WebSocket以及http与https重新总结一.Socket网络中的Socket是一个抽象的接口 &#xff0c;而是为了方便使用TCP或UDP而抽象出来的一层 &#xff0c;可以理解为网络中连接的两端。通常被叫做套接字接口.二.WebSocketWebSocket就是其中一种&#xff0c;是为了创建一种双向…

java button中文乱码_java解决中文乱码的几种写法

工作中总会遇到中文乱码问题&#xff0c;以导出文件&#xff0c;文件名称是中文的话&#xff0c;下载下来的文件名称会乱码问题&#xff0c;总结了几种解决文件名乱码的写法&#xff0c;仅供参考。首先定义一个汉语字符串String zhName "错误码模板";一、java.net.U…

java铝轮_为速度而生 JAVA Fuoco铝合金气动公路

人类在追求速度的历史上一直在不断创新&#xff0c;从两个轮子的自行车&#xff0c;到四个轮字的汽车&#xff0c;再到螺旋桨的飞机&#xff0c;追求速度是人类与生俱来的天性。就如同公路车的用途非常多&#xff0c;综合型公路车、耐力型公路车、爬坡型公路车&#xff0c;但唯…

java excel中删除两列_Java 插入、隐藏/显示、删除Excel行或列

概述操作Excel工作表时&#xff0c;对表格中的行或列数据可执行&#xff0c;包括插入、隐藏、显示、删除等在内的多种操作需求&#xff0c;本文将通过Java代码示例演示每种操作的具体实现方法。文中方法使用了Java Excel类库(Free Spire.XLS for Java 免费版)&#xff0c;可通过…

Java0steam_Java学习 - Stream 使用

Java Stream使用这段时间在学数据库和Java&#xff0c;发现Java的Stream实际上和数据库的查询操作非常类似。这里简单介绍Stream的用法&#xff0c;并和Sql Server中的操作联系起来。此文为初学Stream所写&#xff0c;以后对Stream有更深的理解后会重写当我们使用一个流的时候&…

mysql初始化很慢_mysql初始化报错

/var/log/mysql.log 日志报错如上图所示解决方法&#xff1a;SELinux惹的祸通俗的讲就是linux服务器的安全策略解决&#xff1a;临时关闭&#xff1a;setenforce 0永久关闭需要修改配置文件&#xff0c;重启机器&#xff1a;修改/etc/selinux/config 文件将SELINUXenforcing改为…

百度java的线程技术_自我提升(基础技术篇)——java线程简介

前言&#xff1a;虽然自己平时都在用多线程&#xff0c;也能完成基本的工作需求&#xff0c;但总觉得&#xff0c;还是对线程没有一个系统的概念&#xff0c;所以&#xff0c;查阅了一些资料&#xff0c;理解那些大神和官方的资料&#xff0c;写这么一篇关于线程的文章本来想废…