-
Notifications
You must be signed in to change notification settings - Fork 405
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AbstractMethodError When Using Kotlin Extension Functions (reified, inline, and crossinline keywords) with Java Swing Components that Use ActionEvent #412
Comments
Not directly related: it seems this line is needed even when using Shadow JAR: // This will include the Kotlin library jars, it will be needed even though Shadow JAR already includes it
// to solve all warnings that are related to Kotlin without ignoring them
injars(sourceSets.main.get().compileClasspath)
To solve all warnings coming from Kotlin library without using |
It seems this issue is from my side (incorrect configurations), I didn't include tasks.register<proguard.gradle.ProGuardTask>("proguard") {
dependsOn(tasks.shadowJar)
configuration("proguard.pro")
injars(tasks.shadowJar.flatMap { it.archiveFile })
outjars(project.layout.buildDirectory.file("proguard-obfuscated.jar"))
val javaHome = System.getProperty("java.home")
// Automatically handle the Java version of this build.
if (System.getProperty("java.version").startsWith("1.")) {
// Before Java 9, the runtime classes were packaged in a single jar file.
libraryjars("$javaHome/lib/rt.jar")
} else {
// As of Java 9, the runtime classes are packaged in modular jmod files.
libraryjars(
// filters must be specified first, as a map
mapOf("jarfilter" to "!**.jar", "filter" to "!module-info.class"),
"$javaHome/jmods/java.base.jmod"
)
// Needed to support Java Swing/Desktop
libraryjars(
mapOf("jarfilter" to "!**.jar", "filter" to "!module-info.class"),
"$javaHome/jmods/java.desktop.jmod",
)
}
allowaccessmodification()
dontobfuscate()
dontoptimize()
verbose()
// This will include the Kotlin library jars, Shadow JAR already includes it
libraryjars(sourceSets.main.get().compileClasspath)
printmapping(project.layout.buildDirectory.file("proguard-mapping.txt"))
}
And
This issue can still be useful for anyone who has similar issues as it solves other unrelated issues and can be useful to get started with Proguard on Kotlin/JVM in general. |
Hi @ellet0 ! Glad you solved your issue! In these kind of cases, you would normally see "Referenced class not found" warnings or similar which by default would fail the build. But since you added |
Agreed. which made it harder to debug and caused unexpected behavior. It's a common issue since many tutorials and examples online use I appreciate your guidance on this. |
AbstractMethodError with Kotlin Extension Functions and Java Swing ActionEvent Using ProGuard
Description
The title and details might need to be updated, the issue happens when using Kotlin with Kotlin extension function with (
reified
,inline
andcrossinline
) and usage ofaddActionListener
inJComboBox
or any other Swing component likeJButton
I'm uncertain if this problem is isolated to the utilization of Kotlin extension functions (reified, inline, and crossinline keywords) with Java Swing components.
Example of the throwing error
Steps to Reproduce:
Details steps (From Scratch)
Kotlin
and Gradle as the build System, and any JDK version that supports Proguard, for this example, I used both 11 and 17./gradlew wrapper --gradle-version=8.8
build.gradle
orbuild.gradle.kts
(if you use Gradle Kotlin DSL) and update to 2.0.0:application
plugin, add it in theplugins {}
block, and configure it:proguard.pro
file in the root project folder:I wasn't able to use anything that's from Kotlin like extension functions or keywords like
suspend
or Imports from Kotlin even when using:// This will include the Kotlin library jars injars(sourceSets.main.get().compileClasspath)
So I had to use Shadow JAR to build the Fat JAR, in addition to that the JARs that are built by Gradle task
jar
are usually used by Gradle for Gradle modules for example, disabling them will cause issues with GradleThe
build.gradle.kts
(I'm using Gradle Kotlin DSL in this case) will be something like this:If you try to run the Proguard JAR with the following code snippet in
Main.kt
The application will work as expected, once you start using anything from Java Swing you will get warnings and errors, Swing uses reflections, and the code will usually be in the JDK or JRE, if I understand Proguard correctly, it should work as the code of Java Swing won't be in the application as a result it won't be shrunk or minimized by Proguard,
If you update
Main.kt
to the following:You will get warnings when trying to build the minimized JAR by Proguard, either using
ignorewarnings
or adding the following toproguard.pro
file:You might need to ignore more if you're using other Java swing-related Packages.
Or include the following in your Proguard task:
The application now works perfectly as expected, the size is less than before (from 1.7MB to 15,477 bytes (16 KB on disk))
Let's try to move to more advance example:
Running the application, you won't notice any issues,
add the following extension function to
Main.kt
:And use it inside the
addActionListener
lambda block:Running the application and everything seems to work.
Add another extension function:
it can be used with any instance of
JComboBox
or its subclasses. Calling it fromcomboBox
:Launch the Proguard JAR and change the dropdown item in the swing window, you will get an exception:
The issue won't occur when launching the unminimized JAR directly, I don't understand why this is an issue, all those imports are part of the JDK and usually won't be included in the JAR file, I didn't use any usage of reflections or anything else that Proguard can't know (like loading a class dynamically) if it should be removed or keep, I'm interested to know more about Proguard
It's not directly an issue with Proguard or Java Swing, instead, it will only happen when using
crossinline
,reified
andinline
keywords in the function:A workaround is to update the function to remove them:
The application will work without them
Quickly reproduce the issue
Which has minimal steps to reproduce the issue. it only changes
proguard.pro
,build.gradle.kts
,src/main/kotlin/Main.kt
and Gradle wrapperUnzip the folder and navigate to the folder and then run
./gradlew proguard --info && java -jar ./build/proguard-obfuscated.jar
if you're on Linux or macOS, on Windows replacegradlew
withgradlew.bat
Once the window is opened, change the dropdown item to any other item, you will notice the dropdown won't be closed and in the console, you will get an exception:
Expected Behavior:
To be able to run the application with Proguard JAR without
AbstractMethodError
Actual Behavior:
Encountered
AbstractMethodError
when running the Proguard JARWorkarounds
One of the workarounds will solve it
reified
,inline
, andcrossinline
keywords in the extension functionaddActionListener {}
in the Kotlin extension function on the Java swing componentproguard.pro
An example without encountering the issue:
Another example to encounter the issue:
Images
Image
Once you change the dropdown item, you will get an exception, more details in Details steps (From Scratch)
Environment
JDK:
11
or17
ProGuard:
7.5.0
Gradle:
8.8
Kotlin:
2.0.0
Operating System: macOS 14.2.1 (23C71)
Additional Context
2.0.0
, Proguard7.5.0
or Java17
, I was able to reproduce the same issue on Kotlin1.9.24
, Proguard7.4.1
and Java11
Thank you for your efforts.
The text was updated successfully, but these errors were encountered: