相关疑难解决方法(0)

为什么Java类用空行编译不同?

我有以下Java类

public class HelloWorld {
  public static void main(String []args) {
  }
}
Run Code Online (Sandbox Code Playgroud)

当我编译这个文件并在生成的类文件上运行sha256时,我得到了

9c8d09e27ea78319ddb85fcf4f8085aa7762b0ab36dc5ba5fd000dccb63960ff  HelloWorld.class
Run Code Online (Sandbox Code Playgroud)

接下来我修改了类并添加了一个如下所示的空白行:

public class HelloWorld {

  public static void main(String []args) {
  }
}
Run Code Online (Sandbox Code Playgroud)

我再次在输出上运行sha256,期望得到相同的结果,但我得到了

11f7ad3ad03eb9e0bb7bfa3b97bbe0f17d31194d8d92cc683cfbd7852e2d189f  HelloWorld.class
Run Code Online (Sandbox Code Playgroud)

我已阅读此TutorialsPoint文章:

只包含空格的行(可能带有注释)称为空行,Java完全忽略它.

所以我的问题是,由于Java忽略空行,为什么两个程序的编译字节码都不同?

即在该差HelloWorld.class一个0x03字节是由替换0x04字节.

java bytecode compilation javac

206
推荐指数
4
解决办法
1万
查看次数

嵌套类的构造函数的问题


这个问题是关于Java的有趣行为:它在某些情况下为嵌套类生成了额外的(非默认的)构造函数.

这个问题也是关于奇怪的匿名类,Java用这个奇怪的构造函数生成.


请考虑以下代码:

package a;

import java.lang.reflect.Constructor;

public class TestNested {    
    class A {    
        A() {
        }   

        A(int a) {
        }
    }    

    public static void main(String[] args) {
        Class<A> aClass = A.class;
        for (Constructor c : aClass.getDeclaredConstructors()) {
            System.out.println(c);
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

这将打印:

a.TestNested$A(a.TestNested)
a.TestNested$A(a.TestNested,int)
Run Code Online (Sandbox Code Playgroud)

好.接下来,让构造函数A(int a)私有:

    private A(int a) {
    }
Run Code Online (Sandbox Code Playgroud)

再次运行程序.接收:

a.TestNested$A(a.TestNested)
private a.TestNested$A(a.TestNested,int)
Run Code Online (Sandbox Code Playgroud)

这也没关系.但是现在,让我们main()以这种方式修改方法(添加类A创建的新实例):

public static void main(String[] args) {
    Class<A> aClass = A.class;
    for (Constructor c : aClass.getDeclaredConstructors()) {
        System.out.println(c); …
Run Code Online (Sandbox Code Playgroud)

java reflection nested-class

15
推荐指数
2
解决办法
2181
查看次数

不同的Java编译器(供应商不同)会产生不同的字节码

给定相同的主要版本,比如Java 7,做不同的Java编译器(例如,Oracle的热点,JRockit或IBM的J9等......)将给定的java源代码文件编译成相同的bytcode?

扫描Java 7语言规范似乎正在讨论的是语言的语义,而不是将代码转换为字节码.

这个问题与不同的major.minor版本不同,给定供应商生成相同的字节码.这个问题已在这里得到解答- 可能是.

从以下答案Java类文件的创建是否确定?和这个问题的答案是指评论沿侧两个答案上述问题MAJOR.MINOR 12,我收集了答案,我的问题是YES.

上述摘录如下:

JLS留下了许多实现细节,从一个实现到另一个实现.

但是,JLS没有指定从源代码到生成的字节代码的1:1映射,因此您不应该依赖于生成完全相同的字节代码.

然而,这里的评论意味着不同:

它是编译器,即javac,使用BLAH BLAH BLAH创建代码.这与HotSpot无关.

这意味着给定代码X所有javac实现(相同版本/不同供应商)必须生成相同的Y字节码.

我不明白这是怎么回事,但我无法证实它不是(或者我认为,见上文)是正确的.

可以给出明确的答案吗?

java compiler-construction bytecode javac

6
推荐指数
1
解决办法
1758
查看次数

字节码以无证方式随时间变化

今天我在openjdk 7上使用javaagent和instrumentation来探索大型应用程序(如jboss服务器和应用程序)的类.我每隔10秒就调用所有类的重新转换,因此它们的字节码在我的ClassFileTransformer实现中得到.

我的实现只是跟踪类的字节码如何随时间变化.首先,我很惊讶,字段和方法的顺序,方法访问修饰符,常量池的内容和其他类似的东西因检查而异.但是,它仍然记录在案.

没有记录的内容 - 某些项目可以在类中创建常量池并注入方法中.现在我注意到数字值(Longs,Doubles,Floats等)会发生.

这是它在javap中的样子; 之前:

pool:
...
#17 Float NaNf
method:
#1 fload #17 //NaNf
...
Run Code Online (Sandbox Code Playgroud)

在运行时更改类之后:

pool:
...
#17 Float NaNf
#18 Float NaNf
method:
#1 fload #18 //NaNf <- look, it loads #18 now
Run Code Online (Sandbox Code Playgroud)

我仔细检查过,没有附加任何其他变压器或代理商.

为什么JVM不能让我的字节码保持不变?我在哪里可以阅读有关此类优化/转换(或其他什么)?我读过JVM源代码,但这些只会让我更加困惑.

我只是想创建一种实时字节码验证器 - 一种安全工具.

java jvm bytecode

5
推荐指数
1
解决办法
207
查看次数