从多个位置扫描的 Jetty AnnotationParser 警告

Jetty AnnotationParser scanned from multiple locations warning

我有一个使用 Gradle 构建的项目,它实际上是一个 Vaadin 项目,带有一个我使用 Jetty 的 servlet。 在启动时(即 gradle 运行),我从 AnnotationParser 收到了很多关于 类 重复的警告消息。我只复制了一个,因为日志非常冗长:

[INFO ] 11:22:50.375 org.eclipse.jetty.server.Server.doStart() - jetty-9.4.31.v20200723; built: 2020-07-23T17:57:36.812Z; git: 450ba27947e13e66baa8cd1ce7e85a4461cacc1d; jvm 13.0.2+8
[WARN ] 11:22:50.777 org.eclipse.jetty.annotations.AnnotationParser.addParsedClass() - javax.websocket.ClientEndpoint scanned from multiple locations: jar:file:///Users/fox/.gradle/caches/modules-2/files-2.1/javax.websocket/javax.websocket-api/1.0/fc843b649d4a1dcb0497669d262befa3918c7ba8/javax.websocket-api-1.0.jar!/javax/websocket/ClientEndpoint.class, jar:file:///Users/fox/.gradle/caches/modules-2/files-2.1/javax.websocket/javax.websocket-client-api/1.0/afcf19e889d8725576811f8d47ab6c65d9dcbd78/javax.websocket-client-api-1.0.jar!/javax/websocket/ClientEndpoint.class

在这一行中,AnnotationParser 警告我 ClientEndpoint.class 存在于两个罐子中,即 javax.websocket-api-1.0.jarjavax.websocket-client-api-1.0.jar。 使用命令 gradle dependencies 我可以看到:

...
     +--- org.eclipse.jetty.websocket:javax-websocket-client-impl:9.4.31.v20200723
     |    +--- org.eclipse.jetty.websocket:websocket-client:9.4.31.v20200723 (*)
     |    \--- javax.websocket:javax.websocket-client-api:1.0
     +--- org.eclipse.jetty.websocket:websocket-server:9.4.31.v20200723 (*)
     \--- javax.websocket:javax.websocket-api:1.0

在我的 gradle.build 我只有:

dependencies {

    // Vaadin
    implementation enforcedPlatform('com.vaadin:vaadin-bom:18.0.6')
    implementation("com.vaadin:vaadin-core")
    implementation group: 'com.github.appreciated', name: 'vaadin-css-grid', version: '2.0.0'

    // Logging
    implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.13.1'
    implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.13.1'
    implementation group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.13.1'
    
    // Testing
    testImplementation group: 'junit', name: 'junit', version: '4.12'
    testImplementation group: 'org.skyscreamer', name: 'jsonassert', version: '1.5.0'

    // Jetty
    implementation group: 'org.eclipse.jetty', name: 'jetty-server', version: '9.4.31.v20200723'
    implementation group: 'org.eclipse.jetty', name: 'jetty-webapp', version: '9.4.31.v20200723'
    implementation group: 'org.eclipse.jetty.websocket', name: 'websocket-server', version: '9.4.31.v20200723'
    implementation group: 'org.eclipse.jetty.websocket', name: 'javax-websocket-server-impl', version: '9.4.31.v20200723'
}

所有这些日志真的很烦人(它们会大大降低启动速度)而且我不明白它们是否危险。

避免重复的正确方法是什么? 有没有一种技术可以指示 AnnotationParser 只扫描某些依赖项? 我知道这个主题出现在不同的问题中,但我没有找到 gradle 的解决方案或通用的解决方案策略。

谢谢, 斯特凡诺

在 class 路径的多个位置使用相同的 class 名称是个坏主意。

这是Java上最常见的不稳定运行形式!

如果 classloader 中的多个位置存在相同的 class,Java 中的 classloader 无法保证加载顺序行为。

在一个 运行 中,您可能会不小心按您想要的顺序加载 classes,并正确地 运行,然后在以后的某个日期 运行相同的程序和加载顺序不同,现在您 运行 一个不同的 class 版本并且您有意外行为。

解决此问题的唯一方法是清理您的 class 加载程序并确保您只有 1 个版本的 class 您打算使用。

这就是 Jetty 告诉你的。

至于这个特定的 javax.websocket-apijavax.websocket-client-api,您想在 gradle 级别排除 javax.websocket-client-api,因为所有 websocket 客户端 classes 也存在于 javax.websocket-api.

javax.websocket-client-api jar 仅适用于仅使用 javax.websocket 客户端而不使用 javax.websocket 服务器的项目。


采纳了 joakim-erdfelt 的建议 我已经修改了我的 build.gradle 并且这防止了问题:

    implementation ('org.eclipse.jetty.websocket:javax-websocket-server-impl:9.4.31.v20200723')  {
        exclude module: 'javax.websocket-client-api' 
    }

Gradle 文档在此处:Excluding transitive dependencies