为什么javap classname在编译java文件后我在控制台上使用私有方法不存在?
class A
{
private void one(){}
public void two(){}
protected void three(){}
}
Run Code Online (Sandbox Code Playgroud) 我正在阅读有关学习Java的内部课程.我找到了这段代码
class Animal{
class Brain{
}
}
Run Code Online (Sandbox Code Playgroud)
编译后, javap 'Animal$Brain' 输出为
Compiled from "Animal.java"class
Animal$Brain {
final Animal this$0;
Animal$Brain(Animal);
}
Run Code Online (Sandbox Code Playgroud)
它解释了内部类如何在内部类构造函数中获取对其封闭实例的引用.但是,当我将内部类定义为私有时,就像这样
class Animal{
private class Brain{
}
}
Run Code Online (Sandbox Code Playgroud)
然后编译后, javap 'Animal$Brain' 输出为
Compiled from "Animal.java"
class Animal$Brain {
final Animal this$0;
}
Run Code Online (Sandbox Code Playgroud)
那么为什么输出会有所不同呢?为什么没有显示内部类构造函数?在后一种情况下,内部类也获得了封闭类实例的引用.
我正在阅读Herbert Schilds关于java中泛型的类型擦除.据说在类上运行javap应该在类型擦除后给我关于public,package protected和protected字段和方法的字节码信息.但是,我写了以下课程:
class Ambiguity<T, V extends String>{
T ob1;
V ob2;
void set(T o){
ob1 = o;
}
void set(V o){
ob2 = o;
}
}
Run Code Online (Sandbox Code Playgroud)
并在生成的类文件上运行javap并获得以下输出
编译自"Test.java"
class Ambiguity<T, V extends java.lang.String> {
T ob1;
V ob2;
Ambiguity();
void set(T);
void set(V);
}
Run Code Online (Sandbox Code Playgroud)
我期待根据我读到的内容看起来像这样的输出.
Compiled from "Test.java"
class Ambiguity<java.lang.Object, java.lang.String> {
java.lang.Object ob1;
java.lang.String ob2;
Ambiguity();
void set(java.lang.Object);
void set(java.lang.String);
}
Run Code Online (Sandbox Code Playgroud)
我在这里错过了什么吗?我应该补充一点,我理解以上述方式重载方法不是一个好习惯.我只是看到有兴趣在这种模棱两可的情况下看到javap的结果.
编辑:这似乎是javap中新修复的结果. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4870651
如果我从JDK 1.6运行javap,我会得到我期望的结果.如果我从最初使用的JDK 1.7 b30运行javap,我会得到带有通用信息的结果.
当我用javap反汇编枚举时,enum的隐式构造函数参数似乎缺失了,我无法弄清楚为什么.
这是一个枚举:
enum Foo { X }
Run Code Online (Sandbox Code Playgroud)
我用这个命令编译和反汇编(在Java 8u60上):
javac Foo.java && javap -c -p Foo
Run Code Online (Sandbox Code Playgroud)
这是我得到的输出:
final class Foo extends java.lang.Enum<Foo> {
public static final Foo X;
private static final Foo[] $VALUES;
public static Foo[] values();
Code:
0: getstatic #1 // Field $VALUES:[LFoo;
3: invokevirtual #2 // Method "[LFoo;".clone:()Ljava/lang/Object;
6: checkcast #3 // class "[LFoo;"
9: areturn
public static Foo valueOf(java.lang.String);
Code:
0: ldc #4 // class Foo
2: aload_0
3: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
6: checkcast #4 …Run Code Online (Sandbox Code Playgroud) 我写了下面的代码
public class Reader1 {
private int pageNumber;
private class ReaderName1{
public int getPage(){
return pageNumber;
}
}
static class ReaderFound{
}
}
Run Code Online (Sandbox Code Playgroud)
当我在已编译的代码上使用Java类文件反汇编程序javap时
1. for Reader1.class
class Reader1$ReaderName1 {
final Reader1 this$0;
private Reader1$ReaderName1(Reader1);
public int getPage();
}
2. for Reader1$ReaderName1.class
public class Reader1 {
private int pageNumber;
public Reader1();
static int access$000(Reader1);
}
3. for Reader1$ReaderFound.class
class Reader1$ReaderFound {
Reader1$ReaderFound();
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,因为ReaderFound是一个静态类,它怎么能有一个默认的构造函数?如果是这样的话?是允许的吗?
如果允许在Reader1 $ ReaderFound类中找到什么样的构造函数,因为它不能是静态的.(此外,由于构造函数被隐式调用以初始化一个对象,因为ReaderFound是一个静态类,所以我们没有它的对象.我对第一个问题的观点)
我正在javap研究为我的一个类生成的代码,并注意到以下输出:
...
frame_type = 255 /* full_frame */
offset_delta = 11
locals = [ class Test, double, int, double, double, bogus, bogus, int, int, class "[D" ]
stack = []
...
Run Code Online (Sandbox Code Playgroud)
表中那些"假"类型/变量条目的含义是什么locals?它们是如何造成的?它们对生成的代码有什么影响?
类文件是使用Eclipse 3.7编译器生成的,javap来自OpenJDK-1.6b22.
javap关于常量池命令生成的输出的小问题.当javap打印池它定义字符串常量为Asciz字符串,我的理解方式null终止ASCII:
const #20 = Asciz hello world;
Run Code Online (Sandbox Code Playgroud)
这意味着字符串的长度是未知的,并且要解析您将读取每个字节,直到您遇到null.
但是,常量池字符串常量的长度由字符串前面的两个字节定义,并且没有null附加.(常量池规范).
是否javap将字符串定义为Asciz错误或Asciz具有我不知道的其他含义?
这是我的代码片段:
public class Test {
public static void main(String[] args) {
class EnglishHelloThere {
int a=10;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我创建了一个本地类,以便在编译器中没有为本地类中的变量编写任何修饰符时,查看访问修饰符的类型.
这就是我在JAVAP中得到的
Compiled from "Test.java"
class com.Test$1EnglishHelloThere
SourceFile: "Test.java"
EnclosingMethod: #21.#23 // com.Test.main
InnerClasses:
#27= #1; //EnglishHelloThere=class com/Test$1EnglishHelloThere
minor version: 0
major version: 51
flags: ACC_SUPER
Constant pool:
#1 = Class #2 // com/Test$1EnglishHelloThere
#2 = Utf8 com/Test$1EnglishHelloThere
#3 = Class #4 // java/lang/Object
#4 = Utf8 java/lang/Object
#5 = Utf8 a
#6 = Utf8 I
#7 = Utf8 <init>
#8 …Run Code Online (Sandbox Code Playgroud) 我知道这个调试信息在编译时包含在.class文件中:
javac -g Main.java
Run Code Online (Sandbox Code Playgroud)
并且可以从以下LineNumberTable:部分手动观察:
javap -c -constants -private -verbose '$<' > '$@'
Run Code Online (Sandbox Code Playgroud)
我想要的是javap在字节码的中间显示源.
样本输入:
public class New {
public static void main(String[] args) {
System.out.println(new Integer(1));
}
}
Run Code Online (Sandbox Code Playgroud)
实际javap产量:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: new #3 // class java/lang/Integer
6: dup
7: iconst_1
8: invokespecial #4 // Method java/lang/Integer."<init>":(I)V
11: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
14: return
LineNumberTable:
line 3: 0
line 4: 14
Run Code Online (Sandbox Code Playgroud)
期望的javap输出:
System.out.println(new Integer(1));
0: getstatic #2 // …Run Code Online (Sandbox Code Playgroud) 如果我编译以下源代码:
1. public class Example {
2. public boolean foo(boolean a, boolean b, char ch) {
3. if (a && Character.isLetter(ch)
4. || b && Character.isDigit(ch)
5. || !a && !b) {
6. return true;
7. }
8. return false;
9. }
10. }
Run Code Online (Sandbox Code Playgroud)
使用 Java-7(OpenJDK 或 Oracle),我得到以下 LineNumberTable:
line 3: 0
line 6: 30
line 8: 32
Run Code Online (Sandbox Code Playgroud)
但是,使用 Java 8(OpenJDK 或 Oracle)编译相同的源代码,我得到另一个 LineNumberTable:
line 3: 0
line 4: 16
line 6: 30
line 8: 32
Run Code Online (Sandbox Code Playgroud)
为什么 Java 7 返回的 …
java ×10
javap ×10
bytecode ×2
.class-file ×1
class ×1
decompiling ×1
ecj ×1
enums ×1
generics ×1
oop ×1
type-erasure ×1