ClassNotFoundException 使用带有本地 class 和 Debezium Engine 的 QuarkusClassLoader

ClassNotFoundException using QuarkusClassLoader with local class and Debezium Engine

ClassLoader classLoader = QuarkusClassLoader.getSystemClassLoader();
String str = "com.mycompany.service.SomeClass";
try {
  Class<? extends SomeClass> someClass =
      (Class<? extends SomeClass>) classLoader.loadClass(str);
} catch (Throwable e) {
  e.printStackTrace();
}

我想弄清楚为什么我在尝试加载 com.mycompany.service.SomeClass 时得到 java.lang.ClassNotFoundException。此 class 是在项目本地定义的,当我启动我的 Quarkus 应用程序时出现此错误(mvn compile quarkus:dev)。如果我使用另一个 class 加载程序(即 this.getClass().getClassLoader()),则不会发生此错误。似乎它只发生在 QuarkusClassLoader

编辑: 我认为最终问题与 Debezium 引擎初始化有关。调用以下行时抛出该异常:

// Create the engine with this configuration ...
engine =
    DebeziumEngine.create(Json.class)
        .using(props)
        .notifying(this::handleDbChangeEvent)
        .build();

查看我的回答,了解我是如何修复它的

使用 Classloader.getSystemClassLoader 当然不是正确的做法,因为在开发模式下(更一般地说,你很少想在 Java 代码中这样做),Quarkus 点不是平面类加载器结构,而是分层结构。

有关开发模式下类加载如何工作的更多详细信息,请参见https://quarkus.io/guides/class-loading-reference

您可以强制所有 类 个 jar 由系统类加载器而不是 Quarkus 类加载器加载,方法是使用类似的东西:

quarkus.class-loading.parent-first-artifacts=stax:stax-api

基本上配置 groupId 和应该由系统 ClassLoader 加载的 jar 的 artifactId 的地方

我通过在引擎初始化中传递 Thread.currentThread().getContextClassLoader() 来解决这个问题。

engine =
    DebeziumEngine.create(Json.class)
        // Have to pass the current class loader to avoid ClassNotFoundException
        .using(Thread.currentThread().getContextClassLoader())
        .using(props)
        .notifying(this::handleDbChangeEvent)
        .build();