- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
ClassReader classReader = new ClassReader(new FileInputStream(new File("input.class")));
ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
Files.write(Paths.get("output.class"), classWriter.toByteArray());
反编译output.class
时我得到
package corrupted_class_files;
input.class
很好,我可以使用 ClassReader
来读取说明,只是无法保存类
最佳答案
您的代码缺少将类功能从源实际复制到目标的步骤:
try(FileInputStream in = new FileInputStream(new File("input.class")) {
ClassReader classReader = new ClassReader(in);
ClassWriter classWriter = new ClassWriter(classReader, 0);
classReader.accept(classWriter, 0);
Files.write(Paths.get("output.class"), classWriter.toByteArray());
}
将 ClassReader
传递给 ClassWriter
的构造函数不会复制功能,而是可以进行优化(如果您的转换保留了大部分原始类文件)。或者,如the documentation of ClassWriter(ClassReader classReader, int flags)
说:
Constructs a new ClassWriter object and enables optimizations for "mostly add" bytecode transformations. These optimizations are the following:
- The constant pool and bootstrap methods from the original class are copied as is in the new class, which saves time. New constant pool entries and new bootstrap methods will be added at the end if necessary, but unused constant pool entries or bootstrap methods won't be removed.
- Methods that are not transformed are copied as is in the new class, directly from the original class bytecode (i.e. without emitting visit events for all the method instructions), which saves a lot of time. Untransformed methods are detected by the fact that the ClassReader receives MethodVisitor objects that come from a ClassWriter (and not from any other ClassVisitor instance).
因此,当您在 accept
方法中将 ClassWriter
直接链接到 ClassReader
时,所有方法访问者都将源自 writer,因此,都是直接复制的。
当您要对类进行重大更改或构造新类时,您可以使用构造函数 ClassWriter(int flags)
来代替。
请注意,COMPUTE_FRAMES
已经暗示了 COMPUTE_MAXS
。在上面的示例中,我没有指定任何一个,因为无论如何都会复制方法。当您要实际更改或添加代码并需要 COMPUTE_FRAMES
时,值得向读者指定 SKIP_FRAMES
,因为在重新计算原始帧时解码原始帧是没有意义的无论如何,从头开始。
因此,典型的转换设置如下所示:
public class MyClassVisitor extends ClassVisitor {
public MyClassVisitor(ClassVisitor cv) {
super(Opcodes.ASM5, cv);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor visitor = super.visitMethod(
access, name, desc, signature, exceptions);
if(method matches criteria) {
visitor = new MyMethodVisitorAdapter(visitor);
}
return visitor;
}
}
try(FileInputStream in = new FileInputStream(new File("input.class"))) {
ClassReader classReader = new ClassReader(in);
ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_FRAMES);
classReader.accept(new MyClassVisitor(classWriter), ClassReader.SKIP_FRAMES);
Files.write(Paths.get("output.class"), classWriter.toByteArray());
}
当通过构造函数链接访问者时,您不重写的每个方法都会委托(delegate)给链接的访问者,当最终目标是 ClassWriter 时复制原始构造。由 ClassWriter
提供的 MethodVisitor
。如果该方法不满足您的转换条件,因此您返回原始 MethodVisitor
,则上述优化仍然适用。方法访问者遵循与类访问者相同的模式,覆盖您想要拦截的那些方法。
顺便说一句,您应该避免混合旧的 I/O 和 NIO。代码的简化变体如下所示
ClassReader classReader = new ClassReader(Files.readAllBytes(Paths.get("input.class")));
ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_FRAMES);
classReader.accept(new MyClassVisitor(classWriter), ClassReader.SKIP_FRAMES);
Files.write(Paths.get("output.class"), classWriter.toByteArray());
注意读写之间的对称性
但是,当您使用getResource
等时,您可能被迫处理InputStream
。但对于可通过系统类加载器访问的类,您也可以将类名传递给 ClassReader(String)
构造函数。
关于java - 为什么这段简单的代码会输出损坏的类文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52824262/
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 8 年前。 Improve this qu
我目前正在尝试制作一个非常简单的应用程序,它会根据一天中的时间问候。我的代码是: open System let read() = Console.Read() let readLine() = Co
我已经运行Elasticsearch服务很长时间了,但是突然遇到了以下情况 由以下原因导致:org.elasticsearch.index.translog.TranslogCorruptedExce
我对执行以下操作的 php 重定向脚本有一个奇怪的问题: 在用户的浏览器中植入 Cookie,或者读取现有 Cookie(如果有)。 将用户重定向到另一个网址(重定向的网址是原始网址中的参数,例如 h
我正在使用 iText 7.0.0(Java 风格),似乎表格单元格 HorizontalAlignment 被忽略,因为 CENTER 和 RIGHT 都不起作用。你能重现这个吗? see th
简而言之: 我有一个可以从多个线程访问的计数器变量。尽管我已经实现了多线程读/写保护,但该变量似乎仍然以不一致的方式同时写入,导致计数器结果不正确。 深入杂草: 我使用的“for 循环”会在后台触发大
我有一个 REST 项目,在访问控制服务类中保存用户的ArrayList。一切都工作正常,直到 REST Web 服务突然抛出 java.util.NoSuchElementException。单步查
已关闭。此问题不符合Stack Overflow guidelines 。它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a software
当我刷新页面时,我无法显示 voteUp/Down,因为如果我执行 voteUp/Down(+1 或 -1) 并刷新页面,这会再次返回 voteUp/Down (0)。过去我使用 JSON,但社区推荐
我正在为离散时间 CPU 调度模拟器编写代码。它只是生成流程并相应地安排它们。我目前正在实现 FCFS 计划。我理解离散时间模拟器的本质,但我在用 C++ 实现时遇到了麻烦。 问题出现在handleN
尝试使用 yum 部署包时出现错误: 2016-07-07 14:14:31,296 - ERROR - error: rpmdb: BDB0113 Thread/process 6723/1
我有一个简单的同步队列 template class SynchronisedQueue { public: void Enqueue(const T& d
我正在使用 hadoop 0.20.append 和 hbase 0.90.0。我将少量数据上传到 Hbase,然后出于评估目的杀死了 HMaster 和 Namenode。在此之后,我向 Hbase
我使用 symfony 框架 1.4 创建了一个网站。我正在使用 sfguard 进行身份验证。 现在,这在 WAMP (windows) 上运行良好。我可以在不同的浏览器上登录多个帐户并使用该网站。
目前我已经实现了 HashMap private static Map cached = new HashMap(); 和 Item 是一个具有属性的对象 Date expireTime 和 byte
我试图将 2 个不同的 WPF 控件绑定(bind)到 ViewModel 中的同一属性,即 CheckBox.IsChecked 和 Expander.IsExpanded。我想要实现的行为是让 C
我希望这是一个简单的问题,但我没有找到答案。 我想让 build.gradle 文件通过替换某些变量来设置我的 Spring Boot 应用程序中的版本。这与广告一样有效: def tokens =
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
这个问题在这里已经有了答案: In a fragment shader, why can't I use a flat input integer to index a uniform array o
我已经下载了 OSM 世界地图。解析时出现异常: osm bound changeset (...) changeset Exception in thread "main" org.xml.sax.
我是一名优秀的程序员,十分优秀!