用Java实现JVM第三章《解析class文件》

这篇文章详细描述了JavaClassReader类的内部结构,包括对无符号整数类型的处理,以及MemberInfo和ConstantPool类的使用,展示了如何解析和访问Javaclass文件中的元数据。
摘要由CSDN通过智能技术生成

case 45:

return;

case 46:

case 47:

case 48:

case 49:

case 50:

case 51:

case 52:

if (this.minorVersion == 0)

return;

}

throw new UnsupportedClassVersionError();

}

private ConstantPool readConstantPool(ClassReader reader) {

return new ConstantPool(reader);

}

public int minorVersion(){

return this.minorVersion;

}

public int majorVersion(){

return this.majorVersion;

}

public ConstantPool constantPool(){

return this.constantPool;

}

public int accessFlags() {

return this.accessFlags;

}

public MemberInfo[] fields() {

return this.fields;

}

public MemberInfo[] methods() {

return this.methods;

}

public String className() {

return this.constantPool.getClassName(this.thisClassIdx);

}

public String superClassName() {

if (this.supperClassIdx <= 0) return “”;

return this.constantPool.getClassName(this.supperClassIdx);

}

public String[] interfaceNames() {

String[] interfaceNames = new String[this.interfaces.length];

for (int i = 0; i < this.interfaces.length; i++) {

interfaceNames[i] = this.constantPool.getClassName(interfaces[i]);

}

return interfaceNames;

}

}

ClassReader.java

package org.itstack.demo.jvm.classfile;

import java.math.BigInteger;

/**

  • http://www.itstack.org

  • create by fuzhengwei on 2019/5/13

  • java虚拟机定义了u1、u2、u4三种数据类型来表示;1字节、2字节、4字节,无符号整数。

  • 在如下实现中,用增位方式表示无符号类型:

  • u1、u2可以用int类型存储,因为int类型是4字节

  • u4 需要用long类型存储,因为long类型是8字节

*/

public class ClassReader {

private byte[] data;

public ClassReader(byte[] data) {

this.data = data;

}

//u1

public int readUint8() {

byte[] val = readByte(1);

return byte2int(val);

}

//u2

public int readUint16() {

byte[] val = readByte(2);

return byte2int(val);

}

//u4

public long readUint32() {

byte[] val = readByte(4);

String str_hex = new BigInteger(1, val).toString(16);

return Long.parseLong(str_hex, 16);

}

public float readUint64TFloat() {

byte[] val = readByte(8);

return new BigInteger(1, val).floatValue();

}

public long readUint64TLong() {

byte[] val = readByte(8);

return new BigInteger(1, val).longValue();

}

public double readUint64TDouble() {

byte[] val = readByte(8);

return new BigInteger(1, val).doubleValue();

}

public int[] readUint16s() {

int n = this.readUint16();

int[] s = new int[n];

for (int i = 0; i < n; i++) {

s[i] = this.readUint16();

}

return s;

}

public byte[] readBytes(int n) {

return readByte(n);

}

private byte[] readByte(int length) {

byte[] copy = new byte[length];

System.arraycopy(data, 0, copy, 0, length);

System.arraycopy(data, length, data, 0, data.length - length);

return copy;

}

private int byte2int(byte[] val) {

String str_hex = new BigInteger(1, val).toString(16);

return Integer.parseInt(str_hex, 16);

}

}

MemberInfo.java

package org.itstack.demo.jvm.classfile;

import org.itstack.demo.jvm.classfile.attributes.AttributeInfo;

import org.itstack.demo.jvm.classfile.attributes.impl.CodeAttribute;

import org.itstack.demo.jvm.classfile.attributes.impl.ConstantValueAttribute;

import org.itstack.demo.jvm.classfile.constantpool.ConstantPool;

/**

  • http://www.itstack.org

  • create by fuzhengwei on 2019/4/26

*/

public class MemberInfo {

private ConstantPool constantPool;

private int accessFlags;

private int nameIdx;

private int descriptorIdx;

private AttributeInfo[] attributes;

public MemberInfo(ClassReader reader, ConstantPool constantPool) {

this.constantPool = constantPool;

this.accessFlags = reader.readU2ToInt();

this.nameIdx = reader.readU2ToInt();

this.descriptorIdx = reader.readU2ToInt();

this.attributes = AttributeInfo.readAttributes(reader, constantPool);

}

public static MemberInfo[] readMembers(ClassReader reader, ConstantPool constantPool) {

int fieldCount = reader.readU2ToInt();

MemberInfo[] fields = new MemberInfo[fieldCount];

for (int i = 0; i < fieldCount; i++) {

fields[i] = new MemberInfo(reader, constantPool);

}

return fields;

}

public int accessFlags() {

return this.accessFlags;

}

public String name() {

return this.constantPool.getUTF8(this.nameIdx);

}

public String descriptor() {

return this.constantPool.getUTF8(this.descriptorIdx);

}

public CodeAttribute codeAttribute() {

for (AttributeInfo attrInfo : attributes) {

if (attrInfo instanceof CodeAttribute) return (CodeAttribute) attrInfo;

}

return null;

}

public ConstantValueAttribute ConstantValueAttribute() {

for (AttributeInfo attrInfo : attributes) {

if (attrInfo instanceof ConstantValueAttribute) return (ConstantValueAttribute) attrInfo;

}

return null;

}

}

Main.java

package org.itstack.demo.jvm;

import org.itstack.demo.jvm.classfile.ClassFile;

import org.itstack.demo.jvm.classfile.MemberInfo;

import org.itstack.demo.jvm.classpath.Classpath;

import java.util.Arrays;

/**

  • http://www.itstack.org

  • create by fuzhengwei on 2019/4/24

*/

public class Main {

public static void main(String[] args) {

Cmd cmd = Cmd.parse(args);

if (!cmd.ok || cmd.helpFlag) {

System.out.println(“Usage: [-options] class [args…]”);

return;

}

if (cmd.versionFlag) {

//注意案例测试都是基于1.8,另外jdk1.9以后使用模块化没有rt.jar

System.out.println("java version “1.8.0"”);

return;

}

startJVM(cmd);

}

private static void startJVM(Cmd cmd) {

Classpath classpath = new Classpath(cmd.jre, cmd.classpath);

System.out.printf(“classpath:%s class:%s args:%s\n”,

classpath, cmd.getMainClass(), cmd.getAppArgs());

//获取className

String className = cmd.getMainClass().replace(“.”, “/”);

ClassFile classFile = loadClass(className, classpath);

assert classFile != null;

printClassInfo(classFile);

}

private static ClassFile loadClass(String className, Classpath classpath) {

try {

byte[] classData = classpath.readClass(className);

return new ClassFile(classData);

} catch (Exception e) {

System.out.println("Could not find or load main class " + className);

return null;

}

}

private static void printClassInfo(ClassFile cf) {

System.out.println("version: " + cf.majorVersion() + “.” + cf.minorVersion());

System.out.println(“constants count:” + cf.constantPool().getSiz());

System.out.format(“access flags:0x%x\n”, cf.accessFlags());

System.out.println(“this class:” + cf.className());

System.out.println(“super class:” + cf.superClassName());

System.out.println(“interfaces:” + Arrays.toString(cf.interfaceNames()));

System.out.println(“fields count:” + cf.fields().length);

for (MemberInfo memberInfo : cf.fields()) {

System.out.format(" %s\n", memberInfo.name());

}

System.out.println("methods count: " + cf.methods().length);

for (MemberInfo memberInfo : cf.methods()) {

System.out.format(" %s\n", memberInfo.name());

}

}

}

测试结果

“C:\Program Files\Java\jdk1.8.0_161\bin\java.exe” “-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2018.3.1\lib\idea_rt.jar=61458:D:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2018.3.1\bin” -Dfile.encoding=UTF-8 -classpath “C:\Program Files\Java\jdk1.8.0_161\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\rt.jar;E:\itstack\git\istack-demo\itstack-demo-jvm\itstack-demo-jvm-03\target\classes;D:\Program Files (x86)\apache-maven-2.2.1\repository\com\beust\jcommander\1.72\jcommander-1.72.jar;D:\Program Files (x86)\apache-maven-2.2.1\repository\org\projectlombok\lombok\1.18.0\lombok-1.18.0.jar;D:\Program Files (x86)\apache-maven-2.2.1\repository\com\alibaba\fastjson\1.2.40\fastjson-1.2.40.jar” org.itstack.demo.jvm.Main -Xjre “C:\Program Files\Java\jdk1.8.0_161\jre” java.lang.String

classpath:org.itstack.demo.jvm.classpath.Classpath@4bf558aa class:java.lang.String args:null

version: 52.0

constants count:540

access flags:0x31

this class:java/lang/String

super class:java/lang/Object

interfaces:[java/io/Serializable, java/lang/Comparable, java/lang/CharSequence]

fields count:5

value [C

hash I

serialVersionUID J

serialPersistentFields [Ljava/io/ObjectStreamField;

CASE_INSENSITIVE_ORDER Ljava/util/Comparator;

methods count: 94

()V

(Ljava/lang/String;)V

([C)V

([CII)V

([III)V

([BIII)V

([BI)V

checkBounds ([BII)V

([BIILjava/lang/String;)V

([BIILjava/nio/charset/Charset;)V

([BLjava/lang/String;)V

([BLjava/nio/charset/Charset;)V

([BII)V

([B)V

(Ljava/lang/StringBuffer;)V

(Ljava/lang/StringBuilder;)V

([CZ)V

length ()I

isEmpty ()Z

charAt (I)C

codePointAt (I)I

codePointBefore (I)I

codePointCount (II)I

offsetByCodePoints (II)I

getChars ([CI)V

getChars (II[CI)V

getBytes (II[BI)V

getBytes (Ljava/lang/String;)[B

getBytes (Ljava/nio/charset/Charset;)[B

getBytes ()[B

equals (Ljava/lang/Object;)Z

contentEquals (Ljava/lang/StringBuffer;)Z

nonSyncContentEquals (Ljava/lang/AbstractStringBuilder;)Z

contentEquals (Ljava/lang/CharSequence;)Z

equalsIgnoreCase (Ljava/lang/String;)Z

compareTo (Ljava/lang/String;)I

compareToIgnoreCase (Ljava/lang/String;)I

regionMatches (ILjava/lang/String;II)Z

regionMatches (ZILjava/lang/String;II)Z

startsWith (Ljava/lang/String;I)Z

startsWith (Ljava/lang/String;)Z

endsWith (Ljava/lang/String;)Z

hashCode ()I

indexOf (I)I

indexOf (II)I

indexOfSupplementary (II)I

lastIndexOf (I)I

lastIndexOf (II)I

lastIndexOfSupplementary (II)I

indexOf (Ljava/lang/String;)I

indexOf (Ljava/lang/String;I)I

indexOf ([CIILjava/lang/String;I)I

indexOf ([CII[CIII)I

lastIndexOf (Ljava/lang/String;)I

lastIndexOf (Ljava/lang/String;I)I

lastIndexOf ([CIILjava/lang/String;I)I

lastIndexOf ([CII[CIII)I

substring (I)Ljava/lang/String;

substring (II)Ljava/lang/String;

subSequence (II)Ljava/lang/CharSequence;

concat (Ljava/lang/String;)Ljava/lang/String;

replace (CC)Ljava/lang/String;

matches (Ljava/lang/String;)Z

contains (Ljava/lang/CharSequence;)Z

replaceFirst (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

replaceAll (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

replace (Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String;

split (Ljava/lang/String;I)[Ljava/lang/String;

split (Ljava/lang/String;)[Ljava/lang/String;

join (Ljava/lang/CharSequence;[Ljava/lang/CharSequence;)Ljava/lang/String;

join (Ljava/lang/CharSequence;Ljava/lang/Iterable;)Ljava/lang/String;

toLowerCase (Ljava/util/Locale;)Ljava/lang/String;

toLowerCase ()Ljava/lang/String;

toUpperCase (Ljava/util/Locale;)Ljava/lang/String;

toUpperCase ()Ljava/lang/String;

trim ()Ljava/lang/String;

toString ()Ljava/lang/String;

toCharArray ()[C

format (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;

format (Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;

valueOf (Ljava/lang/Object;)Ljava/lang/String;

valueOf ([C)Ljava/lang/String;

valueOf ([CII)Ljava/lang/String;

copyValueOf ([CII)Ljava/lang/String;

copyValueOf ([C)Ljava/lang/String;

valueOf (Z)Ljava/lang/String;

valueOf ©Ljava/lang/String;

valueOf (I)Ljava/lang/String;

valueOf (J)Ljava/lang/String;

valueOf (F)Ljava/lang/String;

valueOf (D)Ljava/lang/String;

intern ()Ljava/lang/String;

compareTo (Ljava/lang/Object;)I

()V

Process finished with exit code 0

分享

这次面试我也做了一些总结,确实还有很多要学的东西。相关面试题也做了整理,可以分享给大家,了解一下面试真题,想进大厂的或者想跳槽的小伙伴不妨好好利用时间来学习。学习的脚步一定不能停止!

薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了

Spring Cloud实战

薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了

Spring Boot实战

薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了

面试题整理(性能优化+微服务+并发编程+开源框架+分布式)

valueOf ([C)Ljava/lang/String;

valueOf ([CII)Ljava/lang/String;

copyValueOf ([CII)Ljava/lang/String;

copyValueOf ([C)Ljava/lang/String;

valueOf (Z)Ljava/lang/String;

valueOf ©Ljava/lang/String;

valueOf (I)Ljava/lang/String;

valueOf (J)Ljava/lang/String;

valueOf (F)Ljava/lang/String;

valueOf (D)Ljava/lang/String;

intern ()Ljava/lang/String;

compareTo (Ljava/lang/Object;)I

()V

Process finished with exit code 0

分享

这次面试我也做了一些总结,确实还有很多要学的东西。相关面试题也做了整理,可以分享给大家,了解一下面试真题,想进大厂的或者想跳槽的小伙伴不妨好好利用时间来学习。学习的脚步一定不能停止!

[外链图片转存中…(img-zAfodrAq-1714761308770)]

Spring Cloud实战

[外链图片转存中…(img-rCZYQU08-1714761308770)]

Spring Boot实战

[外链图片转存中…(img-RwgwvIjc-1714761308770)]

面试题整理(性能优化+微服务+并发编程+开源框架+分布式)

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 13
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值