Earth Guardian

You are not LATE!You are not EARLY!

0%

Java 命令行操作

编译执行相关

javac

编译 Java 文件,生成 .class 二进制文件

1
2
3
4
5
public class HelloWorld {
public static void main(String[]agrs) {
System.out.println("HelloWorld!");
}
}

编译并生成:

1
2
3
4
// -d 参数表示指定目录,默认为当前目录
xmt@server005:~/test/java$ javac -d . HelloWorld.java
xmt@server005:~/test/java$ ls
HelloWorld.class HelloWorld.java

java

执行 .class 文件,先判断 HelloWorld.java 文件中是包含包名:

  • 不包含包名,直接执行
    1
    2
    xmt@server005:~/test/java$ java HelloWorld
    HelloWorld!
  • 包含包名,需要显示指定包路径
    比如包名为:com.company.department
    1
    2
    xmt@server005:~/test/java$ java com/company/department/HelloWorld
    HelloWorld!
  • 执行 jar 包中的某个 .class 文件
    java -cp jarPath com.***.Test,其中 jarPathjar 包完整路径名,.class 文件需要完整包名加类名。

注意: 包名之间是反斜杠 /,特别是 Windows 环境中。

javap

反汇编器,可以查看编译器为我们生成的字节码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// -c -v 命令为反编译
xmt@server005:~/test/java$ javap -c -v HelloWorld.class
Classfile /home/xmt/test/java/HelloWorld.class
Last modified Oct 23, 2017; size 425 bytes
MD5 checksum 214f120295cc6d0d5e7983866ad7e1ba
Compiled from "HelloWorld.java"
public class HelloWorld
SourceFile: "HelloWorld.java"
minor version: 0
major version: 51
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #6.#15 // java/lang/Object."<init>":()V
#2 = Fieldref #16.#17 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #18 // HelloWorld!
#4 = Methodref #19.#20 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #21 // HelloWorld
#6 = Class #22 // java/lang/Object
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 main
#12 = Utf8 ([Ljava/lang/String;)V
#13 = Utf8 SourceFile
#14 = Utf8 HelloWorld.java
#15 = NameAndType #7:#8 // "<init>":()V
#16 = Class #23 // java/lang/System
#17 = NameAndType #24:#25 // out:Ljava/io/PrintStream;
#18 = Utf8 HelloWorld!
#19 = Class #26 // java/io/PrintStream
#20 = NameAndType #27:#28 // println:(Ljava/lang/String;)V
#21 = Utf8 HelloWorld
#22 = Utf8 java/lang/Object
#23 = Utf8 java/lang/System
#24 = Utf8 out
#25 = Utf8 Ljava/io/PrintStream;
#26 = Utf8 java/io/PrintStream
#27 = Utf8 println
#28 = Utf8 (Ljava/lang/String;)V
{
public HelloWorld();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0

public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String HelloWorld!
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 3: 0
line 4: 8
}

调试

jps

jps(Java Virtual Machine Process Status Tool)JDK 1.5 提供的一个显示当前所有 java 进程 pid 的命令,简单实用,非常适合在 linux/unix 平台上简单察看当前 java 进程的一些简单情况。命令路径:JAVA_HOME/bin/
java 程序在启动以后,会在 java.io.tmpdir 指定的目录下,就是临时文件夹里,生成一个类似于 hsperfdata_User 的文件夹,这个文件夹里(在 Linux 中为 /tmp/hsperfdata_{userName}/)的文件,名字就是进程的 pid。因此列出当前运行的 java 进程,只是把这个目录里的文件名列一下而已。 至于系统的参数等,就可以解析这几个文件获得。

  • 遇到的问题
    现象:用 ps -ef|grep java 能看到启动的 java 进程,但是用 jps 查看却不存在该进程的 idjconsole、jvisualvm 可能无法监控该进程,其他 java 自带工具也可能无法使用
    分析:jps、jconsole、jvisualvm 等工具的数据来源就是这个文件( /tmp/hsperfdata_userName/pid )。所以当该文件不存在或是无法读取时就会出现 jps 无法查看该进程号,jconsole 无法监控等问题。可以检查该文件权限,或者确定文件是否异常

  • 示例

1
2
3
xmt@server005:/tmp/hsperfdata_xmt$ jps
130257 MyDeadLock
130413 Jps

jstack

语法格式: jstack <pid> 可以用 jps 查看 java 进程 id
jstack 可以定位到线程堆栈,根据堆栈信息我们可以定位到具体代码,所以它在JVM性能调优中使用得非常多。

我们能看到:
* 线程的状态: waiting on condition
* 线程的调用栈
* 线程的当前锁住的资源: <0x*>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
xmt@server005:/tmp/hsperfdata_xmt$ jps
130257 MyDeadLock
130413 Jps
xmt@server005:/tmp/hsperfdata_xmt$ jstack -l 130257
2017-10-30 14:45:07
Full thread dump OpenJDK 64-Bit Server VM (24.91-b01 mixed mode):
"Attach Listener" daemon prio=10 tid=0x00007f0b8c001000 nid=0x1fd6c waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"DestroyJavaVM" prio=10 tid=0x00007f0c6400a000 nid=0x1fcd2 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"2" prio=10 tid=0x00007f0c64130000 nid=0x1fd02 waiting for monitor entry [0x00007f0bf8ada000]
java.lang.Thread.State: BLOCKED (on object monitor)
at MyDeadLock$MyRunnable.run(MyDeadLock.java:42)
- waiting to lock <0x00000006b0f51b18> (a java.lang.Object)
- locked <0x00000006b0f51b28> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
"1" prio=10 tid=0x00007f0c6412e000 nid=0x1fd01 waiting for monitor entry [0x00007f0bf8bdb000]
java.lang.Thread.State: BLOCKED (on object monitor)
at MyDeadLock$MyRunnable.run(MyDeadLock.java:30)
- waiting to lock <0x00000006b0f51b28> (a java.lang.Object)
- locked <0x00000006b0f51b18> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:745)

Locked ownable synchronizers:
- None
...
Found one Java-level deadlock:
=============================
"2":
waiting to lock monitor 0x00007f0b900062c8 (object 0x00000006b0f51b18, a java.lang.Object),
which is held by "1"
"1":
waiting to lock monitor 0x00007f0b90004e28 (object 0x00000006b0f51b28, a java.lang.Object),
which is held by "2"
Java stack information for the threads listed above:
===================================================
"2":
at MyDeadLock$MyRunnable.run(MyDeadLock.java:42)
- waiting to lock <0x00000006b0f51b18> (a java.lang.Object)
- locked <0x00000006b0f51b28> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:745)
"1":
at MyDeadLock$MyRunnable.run(MyDeadLock.java:30)
- waiting to lock <0x00000006b0f51b28> (a java.lang.Object)
- locked <0x00000006b0f51b18> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:745)
Found 1 deadlock.

JVM 常见参数

选项 描述
-XX:+TraceClassLoading 打印类加载日志,别名 -verbose:class
-Xms 初始堆大小。如:-Xms256m
-Xmx 最大堆大小。如:-Xmx512m
-Xmn 新生代大小。通常为最大堆的 1/3 或 1/4。新生代 = Eden + 2 个 Survivor 空间。实际可用空间为 = Eden + From,即 90% 的空间
-XX:NewRatio 新生代与老年代的比例,如 –XX:NewRatio=2,则新生代占整个堆空间的 1/3,老年代占 2/3
-XX:SurvivorRatio 新生代中 EdenSurvivor 的比值。默认值为 8。即 Eden 占新生代空间的 8/10,另外两个 Survivor 各占 1/10
-XX:PretenureSizeThreshold 老年代门限值,大小大于这个值的对象直接分配进老年代,这个参数只对 SerialParNew 收集器生效
-XX:MaxTenuringThreshold 对象从新生代晋升到老年代的年龄阀值,默认为 15
-XX:+PrintGC 开启 GC 打印简单信息,别名 -verbose:gc
-XX:+PrintGCDetails 打印 GC 详细信息,通常默认会包含 -XX:+PrintGC 的信息
-XX:+PrintHeapAtGC 打印 GC 前后的堆信息
-Xss JDK1.5+ 每个线程堆栈大小为 1M 。如果超出抛出 StackOverflowError
-XX:PermSize 永久代(方法区)的初始大小,Java 8 中已经使用元空间,降级
-XX:MaxPermSize 永久代(方法区)的最大值,Java 8 中已经使用元空间,降级
-XX:+HeapDumpOnOutOfMemoryError 让虚拟机在发生内存溢出时 Dump 出当前的内存堆转储快照,以便分析用
-XX:+UseSerialGC 使用 Serial + Serial Old 收集器组合回收内存
-XX:+UseParNewGC 使用 ParNew + Serial Old 收集器组合回收内存
-XX:+UseConcMarkSweepGC 使用 ParNew + CMS + Serial Old 收集器组合回收内存,Serial Old 作为 CMS 失败时的备用收集器
-XX:+UseParallelGC 使用 Parallel Scavenge 收集新生代
-XX:+UseParallelOldGC 使用 Parallel Old 收集老年代,默认同时开启 -XX:+UseParallelGC

其他常见命令

javadoc

javadoc 用来生成 Java 注释和 API 文档。
格式:javadoc -d targetDirectory package.name
示例:javadoc -d mydoc com.android.mycode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
xmt@server005:~/$ javadoc -d mydoc annotation.subdir
Creating destination directory: "mydoc/"
Loading source files for package annotation.subdir...
Constructing Javadoc information...
Standard Doclet version 1.7.0_91
Building tree for all the packages and classes...
Generating mydoc/annotation/subdir/Testable.html...
Generating mydoc/annotation/subdir/TestJavaDoc.html...
Generating mydoc/annotation/subdir/package-frame.html...
Generating mydoc/annotation/subdir/package-summary.html...
Generating mydoc/annotation/subdir/package-tree.html...
Generating mydoc/constant-values.html...
Building index for all the packages and classes...
Generating mydoc/overview-tree.html...
Generating mydoc/index-all.html...
Generating mydoc/deprecated-list.html...
Building index for all classes...
Generating mydoc/allclasses-frame.html...
Generating mydoc/allclasses-noframe.html...
Generating mydoc/index.html...
Generating mydoc/help-doc.html...