20191208 OpenJDK、OracleJDK和性能调优中jstack指令的关系

1、前言

本文不去介绍JVM性能调优怎么操作,也不讲JDK怎么安装,以及各种安装方式的区别,而是讲解由指令jstack指令执行出错提示jstack:command not found的原因及其问题的扩展及其相关的知识。也是自己学习过程中的总结和思考。

如果你也曾遇到过下面的这些问题,有类似的疑惑,那么本文或许会有你有所帮助。

2、遇到的问题

1、以前自己也试过在linux上装jdk,当然了,是参考网上的教程。记得有的文章在第一步是要卸载OpenJDK,没看懂是什么意思,因此又找了其他的文章去安装。
2、想学习JVM性能调优分析,于是参考网上的教程,使用top -Hp pid指令找出进程中占用cpu过高的线程,然后准备使用jstack -pid指令进一步分析,结果不像别人博客中写的打印出一堆信息,而是打印出报错信息,提示没有jstack指令:bash: jstack: command not found,可是百度一查,jstack是jdk自带的指令;
3、执行jstack指令报错提示说没有该指令,但是执行java -version却又是正常的,说明不是因为没有配置环境变量的问题。难道真的没有jstack指令吗?于是想要到jdk安装路径下查看是否真的没有jstack指令。参考网上教程的各种方法如打印echo $JAVA_HOME以及which java以及whereis java,结果echo打印出来的是空,而which javawhereis java打印出来的是java指令的执行路径,并非安装路径。那么jdk到底装在了哪里?
4、过段时间再来学习线上程序CPU占用率过高的分析处理,参考了其他的文章,先使用jps指令查看当前所有java程序的进程号,结果又报错了:-bash: jps: command not found,于是换一台服务器,竟然执行jps成功了,jstack指令也成功执行了,可是为什么之前那台服务器却不行呢,到底是什么原因?
5、同事说他负责的某个程序功能很少,可是不知道为什么CPU使用率特别高,于是也是想通过jpsjstack等指令去了解原因,可是也是提示command not found

3、突破口——OpenJDK和OracleJDK

很多问题看看似无关,但其实也是有关联的,只要我们找到突破口,或者有人给我们指点一下,我们就会恍然大悟。像上面的几个问题,在了解JDK还分OracleJDK和OpenJDK以及了解他们的区别之后,或许我们就很快能理解并上面的解决了。

4、OracleJDK和OpenJDK

先来简单了解下OracleJDK和OpenJDK:

Oracle JDK便是平常我们在windows系统上做开发使用的JDK,又称作SUN JDK。OpenJDK则是大多数linux系统版本自带的JDK。OpenJDK的特点是更新频繁,开源免费,可以自由使用。而Oracle JDK的特点是提供稳定可用的商业版本,商用收费,学习研究免费。
参考文章:https://www.cnblogs.com/vast-yj1234/p/11262767.html

OpenJDK和OracleJDK的区别:

Java由SUN公司(Sun Microsystems, 发起于美国斯坦福大学, SUN是Stanford University Network的缩写)发明,2006年SUN公司将Java开源,此时的JDK即为OpenJDK。
也就是说,OpenJDK是Java SE的开源实现,它由SUN和Java社区提供支持,2009年Oracle收购了Sun公司,自此Java的维护方之一的SUN也变成了Oracle 。
Oracle JDK是基于OpenJDK源代码构建的,因此Oracle JDK和OpenJDK之间没有重大的技术差异。
参考文章:https://www.cnblogs.com/shoufeng/p/9719995.html

简而言之,Java是Sun公司发明,并于2006年将其开源并命名为OpenJDK,在此之前是叫SunJDK,而2009年Oracle公司收购了Sun公司,改名为OracleJDK。自此,就有了OpenJDK和OracleJDK,以及其他基于OpenJDK改进的其他版本如IBM J9, Azul Zulu, Azul Zing。而OracleJDK的开源,是不针对商业使用的,因此如果商业上要使用,则需要付费。但是你可以选择使用OpenJDK,OpenJDK依旧在维护并且其更新频率更高。有的Linux服务器上,会默认装上OpenJDK。

5、Linux服务器上的JDK版本

前面说了,有的Linux服务器上,会默认装上OpenJDK。如果没有,则需要我们自己去下载安装。或者当你想要装的是OracleJDK时,就㤇我们自己重新去下载安装JDK。这也就是为什么有的JDK安装教程的博客里面会提到第一步是卸载系统自带的OpenJDK。总之,我们可以根据需要选择下载安装OpenJDK或OracleJDK,相比之下OracleJDK的功能会更全一些,因此我们通常安装OracleJDK,可是商用使用的话OracleJDK是需要付费的,否则则是属于侵权了吧?

当我们下载并安装好JDK后,我们通常使用java -version来查看jdk是否配置好。我们通常最多只会关注输出信息中的jdk版本是1.7还是1.8还是其他,而不会有更多的注意。现在我们知道JDK是分OracleJDK和OpenJDK之后,我们再来仔细看看java -vesion的输出信息:

[liweizhi@iZ23vmlb2osZ ~]$ java -version
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

那在我们之前执行jstack pid指令时会报错提示bash: jstack: command not found的服务器上再执行一次java -version看看:

[liweizhi@iZ2389g2laeZ bin]$ java -version
openjdk version "11.0.4" 2019-07-16 LTS
OpenJDK Runtime Environment 18.9 (build 11.0.4+11-LTS)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.4+11-LTS, mixed mode, sharing)

可以看到,一个写的是java(其实也就是OracleJDK)而另一个写的是OpenJDK。通过对其他服务器进行测试,发现所有出现command not found的服务器都是使用的OpenJDK版本。也就是说,jstack pid执行不了大概是跟JDK版本有关的,可能是OpenJDK不包含jstack指令,当然了,也可以能是因为我们所用的OpenJDK没有下载jstack指令。

6、Linux下查找JDK默认安装路径

于是想要进一步到jdk安装路径下查看是否真的没有jamp、jps、jstack指令,终于通过这篇文章找到了正确寻找Linux下jdk安装路径的方法:https://www.cnblogs.com/756623607-zhang/p/11442320.html。

步骤如下:

1、查看jdk是否安装以及查看java版本——java -version

[liweizhi@iZ23vmlb2osZ bin]$ java -version
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

2、查看java命令的执行位置——which java

[liweizhi@iZ23vmlb2osZ ~]$ which java
/usr/bin/java

3、查找java命令的位置所对于的软链地址——ls -l /usr/bin/java

[liweizhi@iZ23vmlb2osZ ~]$ ls -l /usr/bin/java
lrwxrwxrwx 1 root root 22 Aug 15  2018 /usr/bin/java -> /etc/alternatives/java

4、最后通过软链地址查找JDK的安装目录——ls -l /etc/alternatives/java

[liweizhi@iZ23vmlb2osZ ~]$ ls -l /etc/alternatives/java
lrwxrwxrwx 1 root root 41 Aug 15  2018 /etc/alternatives/java -> /usr/java/jdk1.8.0_181-amd64/jre/bin/java

7、查看JDK安装路径下是否有jstack、jps

对于OracleJDK版本的JDK,在其安装路径下的/usr/java/jdk1.8.0_181-amd64/bin位置下,可以发现确实是有jstack、jmap、jps等指令的:

[liweizhi@iZ23vmlb2osZ bin]$ pwd
/usr/java/jdk1.8.0_181-amd64/bin
[liweizhi@iZ23vmlb2osZ bin]$ ls
appletviewer  jarsigner       javah         jcmd      jhat   jmc.ini     jstat              native2ascii  rmid         tnameserv
ControlPanel  java            javap         jconsole  jinfo  jps         jstatd             orbd          rmiregistry  unpack200
extcheck      javac           javapackager  jcontrol  jjs    jrunscript  jstatd.all.policy  pack200       schemagen    wsgen
idlj          javadoc         java-rmi.cgi  jdb       jmap   jsadebugd   jvisualvm          policytool    serialver    wsimport
jar           javafxpackager  javaws        jdeps     jmc    jstack      keytool            rmic          servertool   xjc

而对于装了OpenJDK版本的JDK的安装路径下:

[liweizhi@iZ2389g2laeZ bin]$ pwd
/usr/lib/jvm/java-11-openjdk-11.0.4.11-1.el7_7.x86_64/bin
[liweizhi@iZ2389g2laeZ bin]$ ls
java  jjs  keytool  pack200  rmid  rmiregistry  unpack200

可以看出,版本是openjdk-11.0.11-1,而且确实是没有jstack、jmap、jps指令的,甚至连javac指令都没有。

8、是否所有OpenJDK都不包含jstack、jps等指令

实践证明,不是的:

[liweizhi@VM_0_17_centos bin]$ pwd
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.232.b09-0.el7_7.x86_64/bin
[liweizhi@VM_0_17_centos bin]$ ls
appletviewer  idlj       javac    java-rmi.cgi  jdeps  jmap        jstack   native2ascii  rmic         serialver   wsgen
clhsdb        jar        javadoc  jcmd          jhat   jps         jstat    orbd          rmid         servertool  wsimport
extcheck      jarsigner  javah    jconsole      jinfo  jrunscript  jstatd   pack200       rmiregistry  tnameserv   xjc
hsdb          java       javap    jdb           jjs    jsadebugd   keytool  policytool    schemagen    unpack200

也许是系统自带的OpenJDK是最精简的,所有不包含jstack这些指令吧。我们可以使用对JDK进行升级,由于是线上服务,就不敢贸贸然轻举妄动。具体操作可以参考这篇文章:https://blog.csdn.net/qq_32447301/article/details/85109014

9、最后

至此,上面提到的5个问题就全部解决了。如果遇到没有jstack:command not found这样的错误信息也不用害怕了,也知道是什么原因导致的了。思路清晰了,问题也就迎刃而解了,就不需要死马当活马医又卸又装,然后自己也不知道怎么回事就把问题给解决了。

然后,就可以继续学习JVM性能调优了,就可以继续深入理解jstack、jmap等指令了。

你可能感兴趣的:(工作总结,记录,linux学习之路)