Java命令之javap初探

代码星冰乐

专注成就未来

首页 归档 关于

Java命令之javap初探

Feb 26, 2018 | haifeiWu | Java | 阅读
文章目录
  1. 1. 用法摘要
  2. 2. 实例分析
    1. 2.1. 结合代码分析编译器执行过程
  3. 3. 总结

作 者:haifeiWu
原文链接:https://www.hchstudio.cn/article/2018/e84d/
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。


由于版权原因,请阅读原文 --> Java命令之javap初探

关注我们

作 者:haifeiWu
原文链接:https://www.hchstudio.cn/article/2018/e84d/
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。

作 者:haifeiWu
原文链接:https://www.hchstudio.cn/article/2018/e84d/
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。

javap是jdk自带的一个工具在jdk安装目录的/bin下面可以找到,可以对代码反编译,也可以查看java编译器生成的字节码,对代码的执行过程进行分析,了解jvm内部的工作。

下面列举javap命令的常用options及其功能描述,更多功能的使用请自行Google,楼主不做赘述。

用法摘要

1
2
3
4
5
6
7
8
9
10
-help 帮助
-l 输出行和变量的表
-public 只输出public方法和域
-protected 只输出public和protected类和成员
-package 只输出包,public和protected类和成员,这是默认的
-p -private 输出所有类和成员
-s 输出内部类型签名
-c 输出分解后的代码,例如,类中每一个方法内,包含java字节码的指令,
-verbose 输出栈大小,方法参数的个数
-constants 输出静态final常量

实例分析

javap命令分解一个class文件,它根据options来决定到底输出什么。如果没有使用options,那么javap将会输出该class文件中的包,类里的protected和public域以及类里的所有方法。javap将会把它们输出在标准输出上。来看这个例子,先编译(javac)下面这个类。

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
package com.thundersoft.metadata.test.kafka;

import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.junit.Test;

import java.util.Arrays;
import java.util.Properties;

public class KafkaTest {

@Test
public void testProducer() {
Properties props = new Properties();
props.put("bootstrap.servers", "192.168.204.30:9092");
props.put("acks", "all");
props.put("retries", 0);
props.put("batch.size", 16384);
props.put("linger.ms", 1);
props.put("buffer.memory", 33554432);
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

Producer<String, String> producer = new KafkaProducer<>(props);
for(int i = 0; i < 100; i++) {
producer.send(new ProducerRecord<String, String>("my-topic", Integer.toString(i), Integer.toString(i)));
}

producer.close();
}

@Test
public void testKafkaConsumer() {
Properties props = new Properties();
props.put("bootstrap.servers", "192.168.204.30:9092");
props.put("group.id", "test");
props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "1000");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("my-topic"));

while (true) {
ConsumerRecords<String, String> records = consumer.poll(100);
for (ConsumerRecord<String, String> record : records)
System.out.printf("offset = %s, key = %s, value = %s%n", record.topic(), record.key(), record.value());
}
}

public static void main(String[] args) {
int a = 2;
int b = 3;
int sum = a*b;
System.out.println(sum);
}

}

在命令行上键入javap KafkaTest后,输出结果如下

1
2
3
4
5
6
public class com.thundersoft.metadata.test.kafka.KafkaTest {
public com.thundersoft.metadata.test.kafka.KafkaTest();
public void testProducer();
public void testKafkaConsumer();
public static void main(java.lang.String[]);
}

结合代码分析编译器执行过程

这里只关注main方法内部的代码逻辑,main方法代码如下

1
2
3
4
5
6
public static void main(String[] args) {
int a = 2;
int b = 3;
int sum = a*b;
System.out.println(sum);
}

在命令行上键入javap -c KafkaTest后,输出结果如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(java.lang.String[]);
Code:
0: iconst_2
1: istore_1
2: iconst_3
3: istore_2
4: iload_1
5: iload_2
6: imul
7: istore_3
8: getstatic #47 // Field java/lang/System.out:Ljava/io/PrintStream;
11: iload_3
12: invokevirtual #54 // Method java/io/PrintStream.println:(I)V
15: return

如上面代码所,iconst_2 与iconst_3分别代表常量2,3 。istore_1 ,istore_2 分别代表定义两个普通变量,iload_1 , iload_2 分别表示加载istore_1,istore_2 两个变量到数据栈中,imul表示两个变量做乘法运算,结果赋值给变量istore_3,最后将结果输出,程序返回。

在分析这段简单代码的过程中,楼主发现了一个jvm编译命令的网站,分享出来jvm指令。

总结

楼主在上面做了一个简单的代码分析的过程,希望可以帮助到有缘人。javap可以用于反编译和查看编译器编译后的字节码。一般用到的不多,不过平时用javap -c比较多,该命令用于列出每个方法所执行的JVM指令,用来解决比较棘手的逻辑出错的bug是个不错的选择。另外通过字节码和源代码的对比,深入分析java的编译原理及代码执行过程,解决各种Java原理级别的问题。

关注我们

作 者:haifeiWu
原文链接:https://www.hchstudio.cn/article/2018/e84d/
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。

分享
Java
测试环境服务器硬盘塞满问题排查个人博客折腾记
微信关注我们
分类
  • Android8
  • Go4
  • Java59
  • Kafka,Java1
  • Kotlin2
  • Linux1
  • MapReduce1
  • Python2
  • Raft1
  • Redis1
  • ThreadPoolExecutor1
  • go1
  • 工具1
  • 总结8
  • 旅游日记1
标签
Nginx ChanghuiN haifeiWu Android Java 设计模式 hexo Kotlin 算法 MySQL 源码解析 Python Redis golang web Kafka 配置中心 总结 性能优化 旅游日记 Shell Go 问题排查 译文 Docker Spring Boot 工具 学习笔记 WebFlux 性能测试 go 散列表 源码 netty Raft
最近文章
  • Kafka的日志复制机制
  • 从20到21
  • go 并发编程
  • 【译】了解Linux CPU负载-您何时应该担心?
  • Zookeeper 与分布式锁
  • 基于Redis的分布式锁到底安全吗?
  • 【译】Raft 学生指南
  • ThreadPoolExecutor 的简单梳理
  • MapReduce 的简单实现
  • 使用 Map 实现策略模式
福利专区
    免费SSL证书
      阿里云红包
        腾讯云专属福利
        Copyright © 2021 代码星冰乐. Powered by ChanghuiN. 版权所有 晋ICP备15001365号
        特别感谢: 云服务器服务商 、 CDN 服务商