概述
JVM的class文件定义有严格的规范,当虚拟机读取class文件的二进制数据时,JVM虽然不会管该二进制数据是从java编译期编译而来还是其他例如groovy或者kotlin等等编译而来,只要符号jvm定义的规范,就能够读取,也就能在JVM虚拟机上运行
直接上代码,可能有些粗糙,不喜勿喷哈各位大神:
两个类,没细化处理,一个主类,一个配置类,本人IDEA+JDK1.8运行
1、主类HexConvertString.java
public class HexConvertString {
private static volatile LinkedHashMap<String, String> constant_pool = new LinkedHashMap<>(10);//保存常量池解析出来的数据
public static void main(String[] args) {
FileInputStream fin = null;//用来读取class文件的输入流
StringWriter sw = new StringWriter();//保存转化后的十六进制的String流
try {
//本人本地的测试路径
fin = new FileInputStream(new File("X:\Users\csfxy\Desktop\MagnumMain.class"));
int len = 1;
byte[] temp = new byte[len];
//进行16进制的读取转化
for (; (fin.read(temp, 0, len)) != -1; ) {
if (temp[0] > 0xf && temp[0] <= 0xff) {//如果是在16到272之间,证明有两位数了,不需要前面加0
sw.write(Integer.toHexString(temp[0]));
} else if (temp[0] >= 0 && temp[0] <= 0xf) {//对于只有1位的16进制数前边补“0”
sw.write("0" + Integer.toHexString(temp[0]));
} else { //对于int<0的位转化为16进制的特殊处理,因为Java没有Unsigned int,所以这个int可能为负数
sw.write(Integer.toHexString(temp[0]).substring(6));
}
}
String readResult = sw.toString();//输出转化后的十六进制
//解析class 文件16进制
String access_flag = "";//类的访问修饰符
if (readResult.startsWith("cafebabe")) {
StringBuffer sb = new StringBuffer(readResult.substring(8));
//解析版本
long code = hexParseLong(sb.substring(0, ConstantParam.ITEM * 2)) + hexParseLong(sb.substring(ConstantParam.ITEM * 2, ConstantParam.ITEM * 4));
System.out.println("该class文件字节码由" + ConstantParam.JdkVersion.getName(code) + "编译");
sb = new StringBuffer(sb.substring(ConstantParam.ITEM * 4));
// System.out.println(sb.toString());
//解析常量池个数
int CONSTANT_POOL_COUNT = (int) (hexParseLong(sb.substring(0, ConstantParam.ITEM * 2)) - 1);
Sy
最后
以上就是端庄摩托为你收集整理的JVM学习笔记2 --纯手写读取class文件常量池内容并输出的全部内容,希望文章能够帮你解决JVM学习笔记2 --纯手写读取class文件常量池内容并输出所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复