首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用测试代码修补Java 9模块以处理反射

用测试代码修补Java 9模块以处理反射
EN

Stack Overflow用户
提问于 2020-02-06 19:10:37
回答 1查看 367关注 0票数 7

如何在测试运行时将测试添加到我的生产代码中,以便两者都位于同一个Java 9模块中,并且可以使用反射进行访问?

到目前为止,我已经尝试过:

  • 删除Java9模块化(实际上是module-info.java) --它完美地工作了,但不是我想要的。
  • 将我的测试移到一个专门的模块(因此也是包)→,它完美地工作,但不是我想要的。(我希望我的单位-测试接近我的代码。)
  • 使用--patch-module实际上添加了另一个文件夹(在使用--module-path指定的文件夹中)--它使用“普通”代码,但不使用反射,它找不到--module-path指定的类。
    • 使用--patch-module→指定我的测试代码和生产代码,它只在我首先指定的文件夹中找到类。
    • 显式添加--add-opens mymodule/mypackge=mymodule...=ALL-UNNAMED以打开反射,→看起来没有任何效果。

所以我的全部测试内容是:

代码语言:javascript
复制
java \
  --patch-module com.stackoverflow.examplemodule=ModuleInfoTest:ModuleInfoExample \
  --module-path ModuleInfoExample \
  --add-opens com.stackoverflow.examplemodule/com.stackoverflow.examplepackage=com.stackoverflow.examplemodule \
  --add-opens com.stackoverflow.examplemodule/com.stackoverflow.examplepackage=ALL-UNNAMED \
  --module com.stackoverflow.examplemodule/com.stackoverflow.examplepackage.Main

我在一个包含以下子目录和文件的目录中:

  • ModuleInfoExample/module-info.class .module
  • ModuleInfoExample/com/stackoverflow/examplepackage/Main.class
  • ModuleInfoTest/com/stackoverflow/examplepackage/AnyClass.class

我在用:

代码语言:javascript
复制
openjdk version "13.0.2" 2020-01-14
OpenJDK Runtime Environment (build 13.0.2+8)
OpenJDK 64-Bit Server VM (build 13.0.2+8, mixed mode, sharing)

正如我从批准的答案中了解到的那样,我的问题并不是像我所说的那样真正地“访问其他类”。但更像是找到它们(通过扫描类路径/模块路径)。然而,这个部分已经是在另一个StackOverflow问题中回答了了。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-08 19:36:17

Oracle的Java 13 java命令中,您尝试使用以下两个选项:

代码语言:javascript
复制
--add-opens module/package=target-module(,target-module)*
--patch-module module=file(;file)*

但是:

  • --add-opens对您没有帮助,因为它为其他模块打开了一个模块。你只有一个模块。
  • --patch-module必须指定要修补到模块中的目录(或the文件)。我注意到有一个;,而不是像您使用的:。在我看来,您一直在告诉java从模块所在的目录中修补:ModuleInfoExample的文件。

您只需要将来自ModuleInfoTest/的文件添加到您的模块中。我根据你的问题创建了这个结构并运行了它:

汇编:

代码语言:javascript
复制
javac -d target/ModuleInfoExample src/ModuleInfoExample/*.java src/ModuleInfoExample/com/stackoverflow/examplepackage/*.java
javac -cp target/ModuleInfoExample -d target/ModuleInfoTest src/ModuleInfoTest/com/stackoverflow/examplepackage/*.java

从模块运行Main -没有添加类:

代码语言:javascript
复制
java --module-path target/ModuleInfoExample --module com.stackoverflow.examplemodule/com.stackoverflow.examplepackage.Main

prints:
Hello world - I'm private

从模块运行AnyClass -没有添加类-预期的异常

代码语言:javascript
复制
java --module-path target/ModuleInfoExample --module com.stackoverflow.examplemodule/com.stackoverflow.examplepackage.AnyClass

Error: Could not find or load main class com.stackoverflow.examplepackage.AnyClass in module com.stackoverflow.examplemodule

从模块运行AnyClass --将AnyClass添加到包中:

代码语言:javascript
复制
java --module-path target/ModuleInfoExample --patch-module com.stackoverflow.examplemodule=target/ModuleInfoTest --module com.stackoverflow.examplemodule/com.stackoverflow.examplepackage.AnyClass

prints:
Inside AnyClass - calling Main: Hello world - I'm private

  field.get() = I'm private
  field.get() = I'm not private anymore

总结构:

代码语言:javascript
复制
>tree /f
..snip..
C:.
+---src
¦   +---ModuleInfoExample
¦   ¦   ¦   module-info.java
¦   ¦   ¦
¦   ¦   +---com
¦   ¦       +---stackoverflow
¦   ¦           +---examplepackage
¦   ¦                   Main.java
¦   ¦
¦   +---ModuleInfoTest
¦       +---com
¦           +---stackoverflow
¦               +---examplepackage
¦                       AnyClass.java
¦
+---target
    +---ModuleInfoExample
    ¦   ¦   module-info.class
    ¦   ¦
    ¦   +---com
    ¦       +---stackoverflow
    ¦           +---examplepackage
    ¦                   Main.class
    ¦
    +---ModuleInfoTest
        +---com
            +---stackoverflow
                +---examplepackage
                        AnyClass.class

src\ModuleInfoExample\模块-info.java:

代码语言:javascript
复制
module com.stackoverflow.examplemodule {
//  exports com.stackoverflow.examplepackage; // no need to export. Nothing is using this
}

src\ModuleInfoExample\com\stackoverflow\examplepackage\Main.java:

代码语言:javascript
复制
package com.stackoverflow.examplepackage;

public class Main {
  private String privateString = "I'm private";

  public static void main(String[] args) {
    new Main().hello();
  }
  public void hello(){
    System.out.println("Hello world - " + privateString);
  }
}

src\ModuleInfoTest\com\stackoverflow\examplepackage\AnyClass.java:

代码语言:javascript
复制
package com.stackoverflow.examplepackage;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class AnyClass {
  public static void main(String[] args) {
    testhello();
    System.out.println();
    breakhello();
  }

  public static void testhello(){
    System.out.print("Inside AnyClass - calling Main: ");
    Main test = new Main();
    test.hello();
  }

  public static void breakhello(){
    try {
      // Not necessary - same package, but..
      Class<?> mainClass = Class.forName("com.stackoverflow.examplepackage.Main");
      Constructor<?> constructor = mainClass.getConstructor();
      Object main = constructor.newInstance();

      // Getting, printing and changing the field..
      Field field = mainClass.getDeclaredField("privateString");
      field.setAccessible(true);
      System.out.println("  field.get() = " + field.get(main));
      field.set(main,"I'm not private anymore");
      System.out.println("  field.get() = " + field.get(main));

    } catch (Exception e) {  // Sorry, all in one big bucket
       System.out.println("Error: " + e);
    }
  }
}
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60101992

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档