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