ClassNotFoundException 使用带有本地类和 Debezium 引擎的 QuarkusClassLoader

Posted

技术标签:

【中文标题】ClassNotFoundException 使用带有本地类和 Debezium 引擎的 QuarkusClassLoader【英文标题】:ClassNotFoundException using QuarkusClassLoader with local class and Debezium Engine 【发布时间】:2021-08-20 18:37:32 【问题描述】:
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。此类是在项目中本地定义的,当我启动我的 Quarkus 应用程序时出现此错误(mvn compile quarkus:dev)。如果我使用另一个类加载器(即 this.getClass().getClassLoader()),则不会发生此错误。似乎它只发生在 QuarkusClassLoader 上

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

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

查看我的回答,了解我是如何解决的

【问题讨论】:

您可以尝试使用Thread.currentThread().getContextClassLoader() 作为类加载器吗? 是的,它可以工作,但我试图弄清楚为什么 QuarkusClassLoader 不能。主要是因为调用它的地方不是我拥有的代码,我只是设法以这种方式重现该错误 【参考方案1】:

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

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

你可以强制一个 jar 的所有类由系统 ClassLoader 而不是 Quarkus ClassLoader 加载,方法是:

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

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

【讨论】:

恐怕我不太明白这意味着什么。有没有办法强制一个类在开发模式下可用? 感谢您更新的答案,不幸的是这也不起作用(我当然尝试使用不同的 groupId:artifactId)。请参阅我的答案以了解有效的方法【参考方案2】:

我通过在引擎初始化中传递 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();

【讨论】:

以上是关于ClassNotFoundException 使用带有本地类和 Debezium 引擎的 QuarkusClassLoader的主要内容,如果未能解决你的问题,请参考以下文章

在 Pax Exam 测试方法中使用匿名类时出现 ClassNotFoundException

使用 kotlin 自定义风格的 ClassNotFoundException

ClassNotFoundException:org.sqlite.JDBC

ClassNotFoundException 使用带有本地类和 Debezium 引擎的 QuarkusClassLoader

Xamarin 使用 CallRedirectionService 引发 Java.Lang.ClassNotFoundException

为啥我在使用 Proguard 时会从 Play Services lib 获得 ClassNotFoundException?