有哪些方法可以在运行时动态生成一个Java类?

在开始今天的学习前,我建议你先复习一下专栏第6讲有关动态代理的内容。作为Java基础模块中的内容,考虑到不同基础的同学以及一个循序渐进的学习过程,我当时并没有在源码层面介绍动态代理的实现技术,仅进行了相应的技术比较。但是,有了上一讲的类加载的学习基础后,我想是时候该进行深入分析了

今天我要问你的问题是,有哪些方法可以在运行时动态生成一个Java类?

典型回答

  • 我们可以从常见的Java类来源分析,通常的开发过程是,开发者编写Java代码,调用javac编译成class文件,然后通过类加载机制载入JVM,就成为应用运行时可以使用的Java类了
  • 从上面过程得到启发,其中一个直接的方式是从源码入手,可以利用Java程序生成一段源码,然后保存到文件等,下面就只需要解决编译问题了
  • 有一种笨办法,直接用ProcessBuilder之类启动javac进程,并指定上面生成的文件作为输入,进行编译。最后,再利用类加载器,在运行时加载即可
  • 前面的方法,本质上还是在当前程序进程之外编译的,那么还有没有不这么low的办法呢?
  • 你可以考虑使用Java Compiler API,这是JDK提供的标准API,里面提供了与javac对等的编译器功能,具体请参考java.compiler相关文档
  • 进一步思考,我们一直围绕Java源码编译成为JVM可以理解的字节码,换句话说,只要是符合JVM规范的字节码,不管它是如何生成的,是不是都可以被JVM加载呢?我们能不能直接生成相应的字节码,然后交给类加载器去加载呢?
  • 当然也可以,不过直接去写字节码难度太大,通常我们可以利用Java字节码操纵工具和类库来实现,比如在专栏第6讲中提到的ASM、Javassist、cglib等

考点分析

  • 虽然曾经被视为黑魔法,但在当前复杂多变的开发环境中,在运行时动态生成逻辑并不是什么罕见的场景。重新审视我们谈到的动态代理,本质上不就是在特定的时机,去修改已有类型实现,或者创建新的类型
  • 明白了基本思路后,我还是围绕类加载机制进行展开,面试过程中面试官很可能从技术原理或实践的角度考察:
    • 字节码和类加载到底是怎么无缝进行转换的?发生在整个类加载过程的哪一步?
    • 如何利用字节码操纵技术,实现基本的动态代理逻辑?
    • 除了动态代理,字节码操纵技术还有那些应用场景