Skip to content
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

Create documentation for the Kotlin Metadata JVM library #4675

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

daniCsorbaJB
Copy link
Contributor

This PR is created to add new documentation for the Kotlin Metadata JVM library.
Related issue: KT-66421

@daniCsorbaJB daniCsorbaJB requested a review from a team as a code owner January 23, 2025 14:28
@@ -0,0 +1,399 @@
[//]: # (title: Kotlin Metadata JVM library)

The [`kotlinx-metadata-jvm`](https://github.com/JetBrains/kotlin/tree/master/libraries/kotlinx-metadata/jvm) library provides tools to read, modify, and generate metadata from Kotlin classes compiled for the JVM.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and further: the library is called kotlin-metadata-jvm, without X

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to kotlin-metadata-jvm everywhere


The [`kotlinx-metadata-jvm`](https://github.com/JetBrains/kotlin/tree/master/libraries/kotlinx-metadata/jvm) library provides tools to read, modify, and generate metadata from Kotlin classes compiled for the JVM.
This metadata, stored in the [`@Metadata`](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-metadata/) annotation within `.class` files,
is used by libraries and tools to inspect Kotlin-specific constructs such as properties, functions,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would emphasise here that it is also used by Kotlin-reflect, and this is why it is important to keep it consistent with what is written in the class file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds like a good idea I like it:

How about modifying it like:
This metadata, stored in the @Metadata annotation within .class files,
is used by libraries and tools, such as kotlin-reflect, to inspect Kotlin-specific constructs such as properties, functions,
and classes at runtime.

The kotlin-reflect library relies on metadata to retrieve Kotlin-specific class details at runtime.
Any inconsistencies between the metadata and the actual .class file may lead to incorrect behavior when using reflection.

{style="note"}

This metadata, stored in the [`@Metadata`](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-metadata/) annotation within `.class` files,
is used by libraries and tools to inspect Kotlin-specific constructs such as properties, functions,
and classes at runtime.
You can also use this library to adjust attributes for binary compatibility validation or to generate and embed metadata into `.class` files.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Binary compatibility validator does not 'adjust' attributes, it simply reads modifiers. What did you mean here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice catch thank you, I originally had something about ASM here but without it doesn't work. 😟

How about:
You can also use the Kotlin Metadata JVM library to read and analyze metadata for binary compatibility checks or to generate and embed metadata into .class files.


## Add the library to your project

To include the Kotlin Metadata JVM library in your project, add the appropriate dependency configuration based on your build tool.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also would mention explicitly that it has the same version as kotlin-stdlib and Kotlin compiler.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, added this line:

The Kotlin Metadata JVM library follows the same versioning as the Kotlin compiler and standard library. Ensure that the version you use matches your project's Kotlin version.


```kotlin
// Imports the necessary library
import kotlin.Metadata
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kotlin.Metadata is located in the standard library, so I'm not sure if 'Imports the necessary library' line is relevant here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point - tested it without and it works - removed this import from everywhere

## Modify metadata

You can use the `kotlinx-metadata-jvm` library to modify Kotlin class metadata, allowing you to adjust visibility attributes,
remove specific declarations, or prepare metadata for binary compatibility checks.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prepare metadata for binary compatibility checks — also seems not related, see my explanation about BCV


You can use the `kotlinx-metadata-jvm` library to modify Kotlin class metadata, allowing you to adjust visibility attributes,
remove specific declarations, or prepare metadata for binary compatibility checks.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also emphasize that modifying metadata is essential if you modify the bytecode in certain ways.
Given that you already have the example of removing private functions, you can write something like this:

"The main goal of modifying metadata is that it should be consistent with existing bytecode. For example, if you are writing a tool like ProGuard, which shrinks the code and may delete some declarations, you have to delete the same declarations from the metadata as well. Let us imagine that we have a JVM tool that deletes private methods from .class files. For that tool to work with Kotlin, it would also have to delete private methods from metadata, which can be done the following way:"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great suggestion, thank you! 💯

I restructured the section a little

e.printStackTrace()
}
}
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also mention that for readStrict/write pair there is a convenient transform shortcut: https://kotlinlang.org/api/kotlinx-metadata-jvm/kotlin-metadata-jvm/kotlin.metadata.jvm/-kotlin-class-metadata/-companion/transform.html

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one - thank you! - I added it as a tip

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use the transform() function instead of separately calling readStrict() and write() separately.
This function parses metadata, applies transformations via a lambda, and writes the modified metadata automatically.

{style="tip"}

These functions allow you to extract detailed information about classes or files, while addressing different compatibility requirements:

* `readLenient()`: Use this function to read metadata, including metadata generated by newer Kotlin compiler versions. However, it doesn't support modifying or writing metadata.
* `readStrict()`: Use this function when you need to modify and write metadata. The `readStrict()` function only works with metadata generated by Kotlin compiler versions fully supported by your project.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also add a link somewhere to the 'Detailed explanation' section of the README in case someone would like to know more about future versions handling

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added it to the note below 👍


## What's next

* [See the API reference for the Kotlin Metadata JVM library](https://kotlinlang.org/api/kotlinx-metadata-jvm/).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe mention 'Module metadata' section of the readme here? It seems lost for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants