如何将类文字编译为Java字节码? [英] How is a class literal compiled to Java bytecode?

查看:187
本文介绍了如何将类文字编译为Java字节码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

public class A {
}

public class B {
    public static void b() {
        System.out.println(A.class);
    }
}

班级文字如何在.class的字节码中编译的A.class ?它是一个现场参考?我在Oracle / Sun的字节码文档中找不到这一点。

How is the class literal A.class compiled in B.class's bytecode? Is it a field reference? I can't find a mention of that in the bytecode documentation from Oracle/Sun.

无论是什么原因,反编译器都可以轻松地重建它:

Decompilers have no trouble reconstructing it, whatever it is:

java -jar decompiler.jar B.class

选择JAVA_TOOL_OPTIONS:' - Dfile.encoding = UTF8'

Picked up JAVA_TOOL_OPTIONS: '-Dfile.encoding=UTF8'


  1. //
    / /由Procyon编译v0.5.30
    //

  1. // // Decompiled by Procyon v0.5.30 //

public class B
{
    public static void b() {
        System.out.println(A.class); <<<
    }
}



推荐答案

在Java 5之前,像 A.class 这样的类文字只是用于调用 Class.forName的语法糖(A)在引擎盖下,将 ClassNotFoundException 转换为 NoClassDefFoundError 和根据编译器,将结果缓存在包含类的合成 static 字段中,即 B

Before Java 5, a class literal like A.class was just syntactic sugar for calling Class.forName("A") under the hood, translating a ClassNotFoundException to a NoClassDefFoundError and, depending on the compiler, cache the result in a synthetic static field of the containing class, i.e. B.

原因是在Java 1.1中引入了类文字作为语言功能,但字节代码没有更改为对它有特殊支持。

The reason is that class literals were introduced in Java 1.1 as a language feature, but the byte code was not changed to have special support for it.

从Java 5开始,类文字被视为实常数,使用单个 ldc ldc_w加载到操作数堆栈指令,就像 String literals一样。不同之处在于常量池项的类型,它指的是字符串常量和 Class_info for Class 常量。

Since Java 5, class literals are treated as real constants, being loaded to the operand stack using a single ldc or ldc_w instruction, just like with String literals. The difference lies in the type of the constant pool item, it refers to, String_info for String constants and Class_info for Class constants.

作为旁注,从Java 7开始,Java字节码甚至允许加载 <$ c $类型的常量c> MethodType MethodHandle ,它没有等效的实际Java语言。

As a side note, since Java 7, the Java bytecode even allows to load constants of type MethodType or MethodHandle which has no actual Java language equivalent.

参见 ldc


index 是一个无符号字节,必须是当前类(第2.6节)的运行时常量池的有效索引。 index 处的运行时常量池条目必须是类型 int float ,或对字符串文字的引用,或对类,方法类型或方法句柄的符号引用(第5.1节)。

The index is an unsigned byte that must be a valid index into the run-time constant pool of the current class (§2.6). The run-time constant pool entry at index either must be a run-time constant of type int or float, or a reference to a string literal, or a symbolic reference to a class, method type, or method handle (§5.1).

如果运行时常量池条目是类型 int float 的运行时常量,数字值该运行时常量的分别作为 int float 推送到操作数堆栈。

If the run-time constant pool entry is a run-time constant of type int or float, the numeric value of that run-time constant is pushed onto the operand stack as an int or float, respectively.

否则,如果运行时常量池条目是引用到类<$ c $的实例c> String 表示字符串文字(第5.1节),然后推送引用到该实例 value 在操作数堆栈上。

Otherwise, if the run-time constant pool entry is a reference to an instance of class String representing a string literal (§5.1), then a reference to that instance, value, is pushed onto the operand stack.

否则,如果运行时常量池条目是对类的符号引用(第5.1节),则命名类被解析(§ 5.4.3.1)和参考 Cl ass 表示该类的对象 value 被推送到操作数堆栈。

Otherwise, if the run-time constant pool entry is a symbolic reference to a class (§5.1), then the named class is resolved (§5.4.3.1) and a reference to the Class object representing that class, value, is pushed onto the operand stack.

否则,运行时常量池条目必须是方法类型或方法句柄的符号引用(第5.1节)。方法类型或方法句柄被解析(第5.4.3.5节)和引用 java.lang.invoke.MethodType的结果实例 java.lang.invoke.MethodHandle ,value被推送到操作数堆栈。

Otherwise, the run-time constant pool entry must be a symbolic reference to a method type or a method handle (§5.1). The method type or method handle is resolved (§5.4.3.5) and a reference to the resulting instance of java.lang.invoke.MethodType or java.lang.invoke.MethodHandle, value, is pushed onto the operand stack.

由于您提到了反编译器,大多数反编译器甚至能够识别更复杂的Java 5之前的代码模式并将它们反编译为类文字。当然,简单的 ldc 指令对于反编译来说是微不足道的。

Since you mentioned decompilers, most decompilers are even capable of recognizing the more complex pre-Java 5 code patterns and decompile them to a class literal. Of course, the simple ldc instruction is trivial to decompile.

这篇关于如何将类文字编译为Java字节码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆