java.lang.NoClassDefFoundError:无法初始化类 – Kotlin对象

huangapple go评论75阅读模式
英文:

java.lang.NoClassDefFoundError: Could not initialize class - Kotlin Object

问题

我有一个使用Kotlin的多模块Gradle项目。
其中一个模块有主方法并依赖其他模块。我需要从该模块创建一个可执行的JAR文件。因此,我尝试通过创建类似下面的Jar任务来实现:

jar {
    manifest {
        attributes(
                'Main-Class': 'my_package.RunnerKt'
        )
    }
    from {
        configurations.compileClasspath.filter{ it.exists() }.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

我还尝试了Shadow Gradle插件
在这两种情况下,都按预期创建了一个fat jar,它似乎包含了所有的类和依赖项。但是,当我用 java -jar 命令运行该jar文件时,我会得到以下错误:
java.lang.NoClassDefFoundError: Could not initialize class my_kotlin_object_class,其中 my_kotlin_object_class 只是一个带有一些变量的Kotlin object

在堆栈跟踪中,没有其他异常会引起这个异常,因此似乎它只是与这个类本身有问题。当我查看JAR文件时,我可以在其中看到这个文件。

我不明白这是否是Kotlin对象本身与可执行JAR文件的问题,还是我做错了什么?

英文:

I have a multi modular Gradle project with Kotlin.
One of the modules have the main method and dependencies to others. I need to create an executable jar from this module. So I have tried to do that by creating a Jar task like this

jar {
    manifest {
        attributes(
                'Main-Class': 'my_package.RunnerKt'
        )
    }
    from {
        configurations.compileClasspath.filter{ it.exists() }.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

And also I tried the Shadow Gradle Plugin.
In both cases the fat jar is created as expected, it seems to have all my classes and dependencies. But when I run the jar with java -jar I get the following error:
java.lang.NoClassDefFoundError: Could not initialize class my_kotlin_object_class where my_kotlin_object_class is just a kotlin object with some variables.

In the stacktrace there are no other exceptions which could cause this one, so seems it just has a problem with this class itself. When I look into the jar, I can see this file there.

I don't understand is this a problem with kotlin object itself and executable jars, or I am doing something wrong?

答案1

得分: 4

所以实际上,在这个异常背后还有另一个异常!

奇怪的是,只要发生异常的类是一个“Kotlin Object”,我就无法在堆栈跟踪中看到真正的异常(我不知道为什么)。
一旦我用一个“class”替换了“object”,我就看到了错误的真正原因。我修复了它,将它改回“object”,一切都如预期般工作。

所以问题本身是针对我的代码的,但其他人也可能会从中受益。
实际上,在那个对象中,我正在使用val url = ClassLoader.getSystemClassLoader().getResource("path_to_file")读取一些配置文件,
这些文件位于模块的resources\configs目录中。在将它们打包到fat jar中后,它们位于jar的根目录下的configs文件夹中。

path_to_file是一个以./开头的相对路径,例如./configs/my_config.json,在我在IntelliJ中运行项目时运行良好,
但在fat jar中,它无法加载文件。令我非常惊讶的是,解决方案只是从路径中删除./前缀,使其变为configs/my_config.json。然后一切都如预期般工作。

英文:

So actually there was another exception behind this one!
The strange thing was that as long as the class that the exception was happening in was a Kotlin Object I was not able to see the real exception in stacktrace (I don't know why).
As soon as I changed the object with a class I saw the real cause of the error. I fixed it, changed back it to object and everything worked as expected.

So the problem itself was specific to my code, but someone might benefit from it as well.
Actually in that object I was reading some configuration files with val url = ClassLoader.getSystemClassLoader().getResource("path_to_file")
these files were in the resources\configs directory of my module. And after packing them into fat jar they were in the root of the jar inside configs folder.

The path_to_file was a relative path starting with ./ e.g. ./configs/my_config.json which is working fine when I run the project in IntelliJ, but inside fat jar it was failing to load the files.
The solution, very surprisingly for me, was just to remove the ./ prefix from the path leaving it just configs/my_config.json. And everything worked as expected.

huangapple
  • 本文由 发表于 2020年8月19日 21:07:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/63487681.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定