标签: bytecode

Java Classloader是否可以重写(仅限其副本)System类的字节码?

所以我有一个类加载器(MyClassLoader),它在内存中维护一组"特殊"类.这些特殊类是动态编译的,并存储在MyClassLoader内的字节数组中.当MyClassLoader被要求提供类时,它首先检查它的specialClasses字典是否包含它,然后再委托给System类加载器.它看起来像这样:

class MyClassLoader extends ClassLoader {
    Map<String, byte[]> specialClasses;

    public MyClassLoader(Map<String, byte[]> sb) {
        this.specialClasses = sb;
    }

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        if (specialClasses.containsKey(name)) return findClass(name);
        else return super.loadClass(name);
    }

    @Override
    public Class findClass(String name) {
        byte[] b = specialClasses.get(name);
        return defineClass(name, b, 0, b.length);
    }    
}
Run Code Online (Sandbox Code Playgroud)

如果我想在其上执行转换(例如检测)specialClasses,我可以简单地通过修改byte[]之前调用defineClass()它来实现.

我还想转换由System类加载器提供的类,但是System类加载器似乎没有提供任何方式来访问byte[]它提供的类的原始类,并Class直接给我提供了对象.

我可以使用一个-javaagent仪器加载到JVM中的所有类,但这会增加我不想检测的类的开销; 我只是想要MyClassLoader加载的类进行检测.

  • 有没有办法检索byte[]父类加载器提供的类的原始,所以我可以在定义自己的副本之前检测它们?
  • 或者,有没有任何方法可以模拟System类加载器的功能,从它抓取它的位置byte[],以便MyClassLoader可以检测和定义自己的所有System类(Object,String等)的副本?

编辑:

所以我尝试了另一种方法:

  • 使用a -javaagent,捕获 …

java bytecode metaprogramming class classloader

14
推荐指数
2
解决办法
5647
查看次数

有没有任何构造函数的JVM字节码类是否有效?

AFAIK,Java中的隐式构造函数总是为没有构造函数的类生成[1],[2].

但在字节码中,我无法在JVMS上找到这样的限制.

所以:

  • 根据JVMS来定义一个没有构造函数的类只有在下面的jasmin hello世界中使用它的静态方法是有效的吗?

  • 除了无法创建它的实例之外还有其他任何后果吗?我将无法使用invokespecial初始化实例,new根据https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.10.2.4,这些实例无效(可以不使用未初始化的对象.

Jasmin代码:

.class public Main
.super java/lang/Object
.method public static main([Ljava/lang/String;)V
    .limit stack 2
    getstatic java/lang/System/out Ljava/io/PrintStream;
    ldc "Hello World!"
    invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
    return
.end method
Run Code Online (Sandbox Code Playgroud)

也就是说,没有构造函数:

.method public <init>()V
    aload_0
    invokenonvirtual java/lang/Object/<init>()V
    return
.end method
Run Code Online (Sandbox Code Playgroud)

运行与java Main给出预期的输出Hello World!.

我检查了javap -v输出,与Java不同,jasmin没有生成默认构造函数.

我还试着打电话new Main();来看看会发生什么:

public class TestMain {
    public static void main(String[] …
Run Code Online (Sandbox Code Playgroud)

java constructor jvm bytecode

14
推荐指数
2
解决办法
1545
查看次数

使用Asm字节码生成器生成具有泛型类型的方法(ClassWriter)

使用Asm可以很容易地定义简单的getter和setter(幸运的是,它甚至可以在FAQ中解释).但是有一件事没有提到,而且我一直无法找到文档,那就是如何使用泛型类型信息来实现它们.

我实际上能够很容易地确定泛型类型信息(因为代码将采用现有的字段和/或方法,并且存在完整的泛型类型处理和解析).我只需要为包含泛型类型的类型生成泛型版本.

我希望这就像修改签名的Asm ClassWriter/MethodVisitor调用一样容易,但文档中的一些注释表明它可能不那么容易(因为泛型信息存储在与常规信息不同的位置).

编辑:看起来入口点是"ClassWriter.visitField/Method(....,String signature) - 请注意,它的"描述"包含正常的非泛型类信息,但术语"签名"(在JLS中)具体指的是到泛型 - 包括类型信息.

java generics code-generation bytecode java-bytecode-asm

13
推荐指数
1
解决办法
2449
查看次数

为什么要解释java字节码?

据我所知,Java编译为Java字节码,然后可以由任何运行Java的机器解释其特定的CPU.Java使用JIT来解释字节码,我知道这样做的速度非常快,但为什么语言设计者一旦检测到正在运行的特定机器,就不会静态编译成机器指令?是否每次通过代码解释字节码?

java interpreter jit bytecode

13
推荐指数
3
解决办法
3520
查看次数

如何观察YARV执行的Ruby字节码

我想观察YARV执行的Ruby字节码,post-mortem.

我怎么能得到这个?

这里有人说这是不可能的.但是,有一个hotruby框架似乎执行ruby字节码,所以我很困惑......

非常感谢!

ruby bytecode vm-implementation

13
推荐指数
1
解决办法
2197
查看次数

为什么在创建新实例时使用DUP

目前我只是在一个使用java字节码的项目中.我经常看到,当创建一个新的类实例并在其上调用一个方法时,字节码将是:

NEW <MyClass>
DUP
INVOKESPECIAL <MyClass.<init>>
Run Code Online (Sandbox Code Playgroud)

这里为什么要做"DUP"?从VM Spec,我得到描述"在操作数堆栈上复制顶部值并将重复的值推送到操作数堆栈".但是为什么在这里需要复制操作数堆栈的最高值呢?谢谢.

java bytecode

13
推荐指数
1
解决办法
1056
查看次数

从Python AST生成.pyc?

我如何从Python AST生成.pyc文件,以便我可以从Python导入文件?

我曾经compile创建过一个代码对象,然后将co_code属性写入文件,但是当我尝试从Python导入文件时,我得到了一个ImportError: Bad magic number in output.pyc.

python bytecode abstract-syntax-tree

13
推荐指数
1
解决办法
2522
查看次数

scala如何生成字节代码?使用像ASM这样的库,还是直接写二进制文件?

我想知道scala如何生成字节代码,它是否使用像ASM这样的库?或者只是将二进制文件写入.class文件以获得性能?

jvm scala bytecode

13
推荐指数
1
解决办法
3557
查看次数

Scala中的包私有范围可从Java中看到

我刚刚从Java代码中使用Scala代码生成的字节码时,我发现Scala范围很奇怪.请考虑使用Spark(Spark 1.4,Hadoop 2.6)的以下代码段:

import java.util.Arrays;
import java.util.List;

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.broadcast.Broadcast;

public class Test {
    public static void main(String[] args) {
        JavaSparkContext sc = 
            new JavaSparkContext(new SparkConf()
                                .setMaster("local[*]")
                                .setAppName("test"));

        Broadcast<List<Integer>> broadcast = sc.broadcast(Arrays.asList(1, 2, 3));

        broadcast.destroy(true);

        // fails with java.io.IOException: org.apache.spark.SparkException: 
        // Attempted to use Broadcast(0) after it was destroyed
        sc.parallelize(Arrays.asList("task1", "task2"), 2)
          .foreach(x -> System.out.println(broadcast.getValue()));
    }
}
Run Code Online (Sandbox Code Playgroud)

这段代码失败了,这是因为我Broadcast在使用它之前自愿销毁它,但问题是在我的心理模型中它甚至不应该编译,更不用说运行正常了.

事实上,Broadcast.destroy(Boolean)声明是private[spark]这样,它不应该从我的代码可见.我会尝试查看字节码,Broadcast但这不是我的专长,这就是我更喜欢发布这个问题的原因.另外,抱歉,我太懒了,不能创建一个不依赖Spark的例子,但至少你明白了.请注意,我可以使用Spark的各种package-private方法,它不仅仅是Broadcast.

知道发生了什么事吗?

java scala bytecode package-private apache-spark

13
推荐指数
1
解决办法
1042
查看次数

是否有可能追踪导致NPE的表达?

当我得到一个NPE时,我会得到一个带行号的堆栈跟踪.这很有用,但是如果行非常密集和/或包含嵌套表达式,那么仍然无法确定哪个引用为null.

当然,这些信息一定在某处可用.有没有办法解决这个问题?(如果不是java表达式,那么至少导致NPE的字节码指令也会有帮助)

编辑#1:我看过一些评论暗示分手等等,没有任何冒犯,实际上是非建设性和无关紧要的.如果我能做到这一点,我会的!我只想说修改源是不可能的.

编辑#2:apangin在下面发布了一个很好的答案,我接受了.但是,对于那些不想自己尝试的人来说,我必须将输出包含在这里!;)

假设我有这个驱动程序TestNPE.java

 1  public class TestNPE {
 2      public static void main(String[] args) {
 3          int n = 0;
 4          String st = null;
 5  
 6          System.out.println("about to throw NPE");
 7          if (n >= 0 && st.isEmpty()){
 8              System.out.println("empty");
 9          }
10          else {
11              System.out.println("othereise");
12          }
13      }
14      
15  }
Run Code Online (Sandbox Code Playgroud)

字节码看起来像这样(仅显示main()方法并省略其他不相关的部分)

Code:
  stack=2, locals=3, args_size=1
     0: iconst_0
     1: istore_1
     2: aconst_null
     3: astore_2
     4: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;                                              
     7: ldc           #3                  // String …
Run Code Online (Sandbox Code Playgroud)

java debugging jvm bytecode stack-trace

13
推荐指数
1
解决办法
332
查看次数