博客
关于我
用Java实现JVM第二章《搜索class文件》
阅读量:614 次
发布时间:2019-03-13

本文共 5830 字,大约阅读时间需要 19 分钟。

Java虚拟机如何寻找并读取class文件

本章节将介绍Java虚拟机如何从指定路径寻找并读取Java类文件的字节码。

环境配置

为了完成本例案例,建议使用以下环境:

  • JDK版本:Java Development Kit 1.8.0
  • IDE:IntelliJ IDEA Community Edition 2018.3.1 x64
  • 编辑器:Notepad++,并预先安装HEX-Editor插件用于查看class文件的字节码

项目结构

项目文件结构如下:

itstack-demo-jvm-02├── pom.xml└── src    ├── main    │    └── java    │         └── org.itstack.demo.jvm    │              ├── classpath    │              │   ├── impl    │              │   │   ├── CompositeEntry.java    │              │   │   ├── DirEntry.java    │              │   │   ├── WildcardEntry.java    │              │   │   └── ZipEntry.java    │              │   ├── Classpath.java    │              │   └── Entry.java    │              ├── Cmd.java    │              └── Main.java    └── test        └── java            └── org.itstack.demo.test                └── HelloWorld.java

代码解析

1. HelloWorld.java

package org.itstack.demo.test;import org.itstack.demo.jvm.classpath.Classpath;import java.util.Arrays;public class HelloWorld {    public static void main(String[] args) {        // 请根据实际需要添加相应的参数        Cmd cmd = Cmd.parse(args);        // 进行JVM启动和类加载等操作    }}

2. Classpath.java

package org.itstack.demo.jvm.classpath;import org.itstack.demo.jvm.classpath.impl.WildcardEntry;import java.io.File;import java.nio.file.Files;import java.nio.file.Paths;public class Classpath {    private Entry bootstrapClasspath;    private Entry extensionClasspath;    private Entry userClasspath;    public Classpath(String jreOption, String cpOption) {        bootstrapAndExtensionClasspath(jreOption);        parseUserClasspath(cpOption);    }    private void bootstrapAndExtensionClasspath(String jreOption) {        String jreDir = getJreDir(jreOption);        // 加载JRE的bootstrap和extension类路径        bootstrapClasspath = new WildcardEntry(jreDir + File.separator + "lib" + File.separator + "*");        extensionClasspath = new WildcardEntry(jreDir + File.separator + "lib" + File.separator + "ext" + File.separator + "*");    }    private String getJreDir(String jreOption) {        if (jreOption != null && Files.exists(Paths.get(jreOption))) {            return jreOption;        }        if (Files.exists(Paths.get("./jre"))) {            return "./jre";        }        String jh = System.getenv("JAVA_HOME");        if (jh != null) {            return Paths.get(jh, "jre").toString();        }        throw new RuntimeException("无法找到JRE目录");    }    private void parseUserClasspath(String cpOption) {        if (cpOption == null) {            cpOption = ".";        }        userClasspath = Entry.create(cpOption);    }    public byte[] readClass(String className) throws Exception {        className = className + ".class";        try {            return bootstrapClasspath.readClass(className);        } catch (Exception e) {            // 忽略        }        try {            return extensionClasspath.readClass(className);        } catch (Exception e) {            // 忽略        }        return userClasspath.readClass(className);    }}

3. Entry.java

package org.itstack.demo.jvm.classpath;import org.itstack.demo.jvm.classpath.impl.CompositeEntry;import org.itstack.demo.jvm.classpath.impl.DirEntry;import org.itstack.demo.jvm.classpath.impl.WildcardEntry;import org.itstack.demo.jvm.classpath.impl.ZipEntry;import java.io.File;import java.io.IOException;public interface Entry {    byte[] readClass(String className) throws IOException;    static Entry create(String path) {        if (path.contains(File.pathSeparator)) {            return new CompositeEntry(path);        }        if (path.endsWith("*")) {            return new WildcardEntry(path);        }        if (path.endsWith(".jar") || path.endsWith(".JAR") || path.endsWith(".zip") || path.endsWith(".ZIP")) {            return new ZipEntry(path);        }        return new DirEntry(path);    }}

测试结果

通过运行Main.java可以看到以下输出结果:

classpath:org.itstack.demo.jvm.classpath.Classpath@4bf558aaclass:E:\itstack\git\istack-demo\itstack-demo-jvm\itstack-demo-jvm-02\target\test-classes\org\itstack\demo\test\HelloWorldargs:nullclassData:ca fe ba be 00 00 00 34 00 22 0a 00 06 00 14 09 00 15 00 16 08 00 17 0a 00 18 00 19 07 00 1b 01 00 06 3c 69 6e 69 74 3e 01 00 03 28 29 56 01 00 04 43 6f 64 65 01 00 0f 4c 69 6e 65 4e 75 6d 62 65 72 54 61 62 6c 65 01 00 12 4c 6f 63 61 6c 56 61 72 69 61 62 6c 65 54 61 62 6c 65 01 00 04 74 68 69 73 01 00 22 4c 6f 72 67 2f 69 74 73 74 61 63 6b 2f 64 65 6d 6f 2f 74 65 73 74 2f 48 65 6c 6c 6f 57 6f 72 6c 64 3b 01 00 04 6d 61 69 6e 01 00 16 28 5b 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00 04 61 72 67 73 01 00 13 5B 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 01 00 0A 53 6F 75 72 63 65 46 69 6C 65 01 00 0F 48 65 6C 6C 6F 57 6F 72 6C 64 2E 6A 61 76 61 0C 00 07 00 08 07 00 1C 0C 00 1D 00 1E 01 00 0D 48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21 07 00 1F 0C 00 20 00 21 01 00 20 6F 72 67 2F 69 74 73 74 61 63 6B 2F 64 65 6D 6F 2F 74 65 73 74 2F 48 65 6C 6C 6F 57 6F 72 6C 64 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01 00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 00 07 70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 00 21 00 05 00 06 00 00 00 00 00 02 00 01 00 07 00 08 00 01 00 09 00 00 00 2F 00 01 00 01 00 00 00 05 2A B7 00 01 B1 00 00 00 02 00 0A 00 00 00 06 00 01 00 00 00 03 00 0B 00 00 00 0C 00 01 00 00 00 05 00 0C 00 0D 00 00 00 09 00 0E 00 0F 00 01 00 09 00 00 00 37 00 02 00 01 00 00 00 09 B2 00 02 12 03 B6 00 04 B1 00 00 00 02 00 0A 00 00 00 0A 00 02 00 00 00 06 00 08 00 07 00 0B 00 00 00 0C 00 01 00 00 00 09 00 10 00 11 00 00 00 01 00 12 00 00 00 02 00 13

通过Notepad++打开HelloWorld.class文件,并使用HEX-Editor插件查看其字节码,可以看到类的具体字节排列。

转载地址:http://ifiaz.baihongyu.com/

你可能感兴趣的文章
php时间戳知识点,php 时间戳函数总结与示例
查看>>
PHP查找数组中最大值与最小值
查看>>
php查最大值,在PHP数组中查找最大值
查看>>
php标签筛选,关于PHP CodeIgniter框架中通过<a>标签和url做多条件分类筛选
查看>>
php根据年月日计算年龄
查看>>
RabbitMQ - 单机部署(超详细)
查看>>
php检查注册,PHP检查注册的电子邮件地址是一个’school.edu’地址
查看>>
php模拟发送GET和POST请求
查看>>
php模板引擎smarty
查看>>
php正则表达式的特殊字符含义
查看>>
PHP水仙花问题解法之一
查看>>
php没有解析是怎么回事,linux下php文件没有被剖析怎么办?_后端开发
查看>>
php注册页面实现注册后跳转页面
查看>>
PHP消息队列的实现方式与详解,值得一看
查看>>
PHP混合Go协程并发
查看>>
php源码中如何添加滚动公告,给WordPress网站添加滚动公告的方法
查看>>
php漏洞tips
查看>>
php版Zencoding之 phpstorm
查看>>
PHP版本升级5.4手记
查看>>
php版本微信公众号开发
查看>>