标签: javap

Scala:用反射来发现你的内心对象(和欲望)?

有没有办法在运行时发现在外部对象内声明的对象?Java的Class方法getClassesgetDeclaredClasses都返回空数组.

object Parent {
    object Child1
    object Child2
}

println("Children of Parent:")
println("   getClasses found %d".format(Parent.getClass.getClasses.size))
println("   getDeclaredClasses found %d".format(Parent.getClass.getDeclaredClasses.size))
Run Code Online (Sandbox Code Playgroud)

输出是:

Children of Parent:
  getClasses found 0
  getDeclaredClasses found 0
Run Code Online (Sandbox Code Playgroud)

编辑:我已经探索让孩子们与父母一起注册:

object Parent {
    val children = new collection.mutable.ListBuffer[AnyRef]
    object Child1 { Parent.children += this }
    object Child2 { Parent.children += this }
}

println("(1) Parent.children size: %d".format(Parent.children.size))
Parent.Child1
Parent.Child2
println("(2) Parent.children size: %d".format(Parent.children.size))
Run Code Online (Sandbox Code Playgroud)

(虽然这看起来很难看,但实际上还可以,因为我可以通过创意子类和隐式参数来隐藏这些细节.)

这种方法的问题是在引用每个类型(因此调用Parent.Child1Parent.Child2)之前不会调用静态初始化器,这会破坏目的.输出是:

(1) Parent.children size: …
Run Code Online (Sandbox Code Playgroud)

reflection scala bytecode javap

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

Java:匿名类的初始化和构造函数

我想了解一个我在处理匿名课程时遇到的奇怪行为.

我有一个类在其构造函数中调用受保护的方法(我知道,设计很差,但这是另一个故事...)

public class A {
  public A() {
    init();
  }
  protected void init() {}
}
Run Code Online (Sandbox Code Playgroud)

然后我有另一个扩展A和覆盖的类init().

public class B extends A {
  int value;
  public B(int i) {
    value = i;
  }
  protected void init() {
    System.out.println("value="+value);
  }
}
Run Code Online (Sandbox Code Playgroud)

如果我编码

B b = new B(10);
Run Code Online (Sandbox Code Playgroud)

我明白了

> value=0
Run Code Online (Sandbox Code Playgroud)

这是预期的,因为超级类的构造函数在Bctor 之前调用然后value仍然是.

但是在使用像这样的匿名类时

class C {
  public static void main (String[] args) {
    final int avalue = Integer.parsetInt(args[0]);
    A a = new A() …
Run Code Online (Sandbox Code Playgroud)

java constructor javac anonymous-class javap

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

使用/不使用断言进行编译时的javap差异

不耐烦的Scala第15章练习10:添加assert(n >= 0factorial方法中.编译启用断言并验证是否factorial(-1)抛出异常.无需断言即可编译.怎么了?使用javap看看发生了什么,以断言通话.

我的代码:

object Test {
  def factorial(x: Int): Int = {
    assert(x >= 0, "Call to factorial must be >= 0!")
    x match {
      case 0 => 1
      case x: Int => x * factorial(x - 1)
    }
  }

  def main(args: Array[String]): Unit = {
    factorial(-1)
  }
}
Run Code Online (Sandbox Code Playgroud)

scalac首先编译,使用检查它javap Test,然后再次编译scalac -Xelide-below MAXIMUM并使用相同的命令进行检查 - 我似乎无法找到两者之间的区别.

我理解使用断言进行编译会在我尝试执行程序时抛出异常,而没有断言的编译会导致堆栈溢出错误,但我找不到javap...

scala javap

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

javap以可编程方式

我们可以通过编程方式在自己的Java代码中使用javap吗?

例如,以下代码:

public class TestClass {
    public static void main(String[] args) {
        System.out.println("hello world");
    }
}
Run Code Online (Sandbox Code Playgroud)

在命令行中使用javap,我们得到了:

// Header + consts 1..22 snipped
const #22 = String      #23;    //  hello world
const #23 = Asciz       hello world;

public static void main(java.lang.String[]);
  Signature: ([Ljava/lang/String;)V
  Code:
   Stack=2, Locals=1, Args_size=1
   0:   getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #22; //String hello world
   5:   invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   return
  // Debug info snipped
}
Run Code Online (Sandbox Code Playgroud)

我可以使用javap的API仅打印常量池吗?

java api javap

4
推荐指数
2
解决办法
1686
查看次数

java:字节码中的字符串concat转换为StringBuilder

我用javac命令行查看了我的编译代码,每当我使用String运算符+运算符时,我就会看到,编译后的代码被StringBuilder的append()方法替换.现在我认为使用StringBuilder和String连接具有相同的性能,因为它们具有相似的字节码,是否正确?

java string stringbuilder jvm javap

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

java JVM 字节码表示法,注释语法。调用动态

问题:第14行是什么意思?

使用 javap -v -c 反汇编以下代码:

 public class test {
     static int i = 2;
     public static void main(String[] args) {
         test x = new test();
         System.out.println("text + String: " + i);
     } 
 }
Run Code Online (Sandbox Code Playgroud)

在主函数中,我们得到以下内容:

14: invokedynamic #20,  0             // InvokeDynamic #0:makeConcatWithConstants:(I)Ljava/lang/String;
19: invokevirtual #24                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
...
BootstrapMethods:
  0: #38 REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
    Method arguments:
      #44 text + String: \u0001
Run Code Online (Sandbox Code Playgroud)

因此,例如,第 19 行表示来自运行时常量池中 #24 项的 invokevirtual 函数。调用的方法println()来自于类java/io/PrintStream,其输入来自于类Ljava/lang/String,其返回值为 Void。

至于第 14 行,#0 持有对 BootstrapMethod …

java jvm javap jvm-bytecode

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

在 java 编译器中标记行时出现问题

我是一名硕士生,正在研究静态分析。在我的一项测试中,我遇到了在 java 编译器中标记行的问题。

我有以下java代码:

 226:   String json = "/org/elasticsearch/index/analysis/commongrams/commongrams_query_mode.json";
 227:   Settings settings = Settings.settingsBuilder()
 228:           .loadFromStream(json, getClass().getResourceAsStream(json))
 229:           .put("path.home", createHome())
 230:           .build();
Run Code Online (Sandbox Code Playgroud)

编译此代码并执行命令时javap -p -v CLASSNAME,我得到一个表,其中包含字节码中每条指令的源代码的相应行。

见下图:

字节码表

问题在于,在对该.put (" path.home ", createHome ())方法的调用中,字节码基本上生成四个指令:

19: anewarray  
24: ldc - String path.home
30: invokespecial - createHome
34: invokevirtual - put

Run Code Online (Sandbox Code Playgroud)

前两行标记为第 228 行(错误),后两行标记为第 229 行(正确)。

见下图:

字节码表

这是该方法的原始实现.put("path.home", createHome())

     public Builder put(Object... settings) {
        if (settings.length == 1) {
            // support cases where the actual …
Run Code Online (Sandbox Code Playgroud)

java bytecode javac javap

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

var arg和array之间的区别

假设我有一个类似的代码

public class HelloWorld {

    public static String method1(String[] array){return ""+array.length;}
    public static String method2(String... array){return ""+array.length;}


    public static void main(String args[]) {
        System.out.println(method1(new String[]{"test"})); //allowed
        //System.out.println(method1("test")); Not allowed
        System.out.println(method2(new String[]{"test"}));  //allowed
        System.out.println(method2("test")); //allowed
    }
}
Run Code Online (Sandbox Code Playgroud)

当我做 javap HelloWorld

C:\Users\athakur\JavaProjectWorkspace\HelloWorld\bin\test>javap HelloWorld
Compiled from "HelloWorld.java"
public class test.HelloWorld extends java.lang.Object{
    public test.HelloWorld();
    public static java.lang.String method1(java.lang.String[]);
    public static java.lang.String method2(java.lang.String[]);
    public static void main(java.lang.String[]);
}
Run Code Online (Sandbox Code Playgroud)

因此,根据类文件method1和method2采用相同的数组参数.那为什么他们可以采取的输入差异?

类似method1不能采用简单的String输入,因为var arg可以采用变量String输入和数组?

java arrays variadic-functions javap

3
推荐指数
1
解决办法
992
查看次数

为什么javac为两个看似非常相似的结构生成不同的字节代码?

考虑一下非常简单的人为设计代码:

 public class TestJavap {
    public static void main(String[] args) {
        int a = 3;
        int b = 7;
    }
}
Run Code Online (Sandbox Code Playgroud)

javap产生这个:

 public static void main(java.lang.String[]);
  Code:
   0: iconst_3      
   1: istore_1      
   2: bipush        7
   4: istore_2      
   5: return       
Run Code Online (Sandbox Code Playgroud)
  1. 为什么编译器非常类似领域生产不同字节码ab.两者都是用常量文字初始化的整数类型.

    因为a它从池中取出常量iconst_3,然后将其存储在变量中,istore_1而对于b,它使用完全不同的机制(bipush和的 组合istore).

java bytecode javap

3
推荐指数
1
解决办法
139
查看次数

使用javap读取字节码

我通过在互联网上阅读发现java编译

public class Test {
    private String s = "TESTTEST";
}
Run Code Online (Sandbox Code Playgroud)

public class Test {
    private String s;

    public Test() {
        s = "TESTTEST";
    }
}
Run Code Online (Sandbox Code Playgroud)

我对吗?

现在我尝试自己去理解这一点。Test.java所以我通过调用来编译该类

javac Test.java
Run Code Online (Sandbox Code Playgroud)

之后,我读到可以用来javap读取编译后的代码(=字节代码)。

因此,我尝试在字节码中查看编译器的重组,我上面提到过(减速在构造函数中)。但如何?这是javap正确的工具吗?如果是,用哪些参数?

感谢您的帮助!

编辑:

好的,到目前为止谢谢!您能解释一下如何读取 的输出javap -c Test吗?

C:\Users\MyName\Desktop>javap -c Test
Compiled from "Test.java"
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: ldc           #2                  // String TESTTEST
       7: putfield      #3                  // …
Run Code Online (Sandbox Code Playgroud)

java javac javap

3
推荐指数
1
解决办法
2437
查看次数