What is the intentional use of @JvmSynthetic in Kotlin?

I came across the @JvmSynthetic annotation in kotlin-stdlib and I wonder what it is for, but unfortunately it is not documented. (UPD: it was at that moment)

As I understand it, applying it to a program element will add a synthetic modifier to the corresponding bytecode elements. As a result, an element becomes invisible from Java:

 class MyClass { @JvmSynthetic fun f() { } } 

Somewhere in the Java code:

 MyClass c = new MyClass(); cf() // Error: cannot resolve method f() 

But the same elements are still visible in the Kotlin code:

 val c = MyClass() cf() // OK 

Is hidden ad from non-Kotlin sources a legitimate use of @JvmSynthetic ? Is this intended use? What are other relevant uses?

Because @JvmSynthetic hides functions from Java, they also cannot be overridden in Java (and when it comes to the abstract member, calls then lead to AbstractMethodError ). Given this, can I use @JvmSynthetic to prevent Kotlin class members from being overridden in Java sources?

+18
java kotlin synthetic
source share
2 answers

First, to answer the question of what are synthetic methods, let's take a look at the Java language specification :

11. A construct emitted by the Java compiler must be marked synthetic if it does not correspond to a construct declared explicitly or implicitly in the source code, unless the emitted construct is a class initialization method (JVMS ยง2.9).

The @JvmSynthetic does just that: it prevents access from source code. The method will still be displayed in reflection, and then will be marked as synthetic.

More precisely, from the Kotlin documentation (highlighted mine):

@JvmSynthetic

Sets the ACC_SYNTHETIC flag for an annotated target in Java bytecode.

Synthetic targets become inaccessible to Java sources at compile time, but remain available to Kotlin sources. Marking a target as synthetic is a binary compatible change, already compiled Java code can access that target.

This annotation is intended for rare cases when an API developer needs to hide a specific Kotlin target from the Java API, leaving it part of the Kotlin API, so the resulting API is idiomatic for both.

As described in the last paragraph, @JvmSynthetic is an API design tool that allows the library developer to avoid automatically generating Java equivalents. Probably the most popular use cases are Kotlin-only functions, such as operator overloading, componentN() methods, or properties that might have a more idiomatic way of representing them in Java.

It should be noted that the purpose of these annotations is to set / get properties, functions, and fields - basically everything that translates into method in Java.

 @Target([ AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.FIELD]) annotation actual class JvmSynthetic 
+3
source share

In simple Java, synthetic methods are generated by the javac compiler. Typically, the compiler should create synthetic methods for nested classes when fields specified using a private modifier gain access to the surrounding class.

Given the following class in java:

 public final class SyntheticSample { public static void main(final String[] args) { SyntheticSample.Nested nested = new SyntheticSample.Nested(); out.println("String: " + nested.syntheticString); } private static final class Nested { private String syntheticString = "I'll become a method!"; } } 

when the SyntheticSample class accesses the nested.syntheticString field, it does indeed invoke the static synthetic method generated by the compiler (called something like access$100 ).

Even if Kotlin provides the @JvmSynthetic annotation, which can "force" create synthetic methods, I advise you not to use it in regular "user" code. Synthetic methods are low-level tricks created by the compiler, and we should never rely on such things in everyday code. I think it's there to support other parts of the standard library, but you should ask the JetBrains guys directly if you're interested (try the official Kotlin Discussion Forum )

+12
source share

All Articles