What Version Of Kotlin Was Used To Compile This Jar? - kotlin

Given a jar file that I know was compiled with kotlin, how do I determine which version of kotlin was used to compile the class files in it?
If I do the following I get 52 (i.e. JDK8)
javap -cp target.jar -verbose fully.qualified.class.name | grep major
That is the java target version though.

I don't think you can, given that (as far as I know) the Kotlin compiler doesn't store any version information in generated classes.
Unlike e.g. Scala, which embeds its major and minor version in the compiled class files, Kotlin only adds #Metadata annotations to methods and classes etc. to hold information about nullability, mutability, etc. You can find the protobuf for this information here.
You could use the older "standard" (which was also used in Scala projects) of embedding the version in the JAR's name.

Related

How to exclude default Java packages in Kotlin?

Head First Kotlin states that if your target platform is the JVM, the following are imported by default:
java,lang.*
kotlin.jvm.*
If I do not want to have dependencies on Java how do I not import the JVM specific packages?
The default imports depend on the platform context under which the sources are analyzed. The imports you specified, kotlin.jvm.* and java.lang.*, are specific to Kotlin/JVM sources. You can't affect the default imports.
If you want to avoid accidentally using those imports, then you most likely have plans to compile your code for the other platforms, Kotlin/JS and Kotlin/Native. In this case, the best choice for you would be to have a multiplatform project with the sources placed in a common source set: such a source set is analyzed as platform-agnostic code which can't use platform-specific language features and dependencies, and the default imports also don't contain anything that is JVM-specific.
You cannot change that, and there is no reason for doing that.
This affects neither performance nor compiled artifact size.
This is just as Kotlin designed.

Error: Declaration annotated with #OptionalExpectation can only be used in common module sources

Update (2018-11-03)
This is a known issue that is being tracked here.
Original Post
I am playing around with Kotlin MPP, specifically with Kotlin 1.3 and the new structure. After converting a Kotlin 1.2 MPP to the new structure, I keep getting these errors:
Error:(3, 18) Kotlin: [MPP_jvmMain] Declaration annotated with '#OptionalExpectation' can only be used in common module sources
These are referring to the #JsName() annotations I have within my common module.
I have tried:
Starting a completely new MPP from scratch using the built-in wizard, and simply adding #JsName("test") to the hello() function that comes with the generated sample. Even that seems to cause problems.
Invalidating caches/restarting IntelliJ
Using the latest versions of everything (Kotlin 1.3, IntelliJ IDEA 2018.2.5 Ultimate)
Calling ./gradlew build from the command line. This works.
Sample project here
Link Kotlin Issue
This was fixed within v1.3.10 of the Kotlin plugin for IntelliJ.

Kotlin runtime jar vs kotlin stdlib jar

What's the difference between kotlin-runtime.jar (225.1K) and kotlin-stdlib.jar (727.3K) (sizes are for 1.0.0-beta-1103 version)? Which one should I distribute with my application? For now I live with kotlin-stdlib.jar, because that's what Android Studio generated, but I wonder if I can use kotlin-runtime.jar since it's smaller.
The runtime library only contains base Kotlin language types required to execute compiled code. It is a minimal classes set required.
The standard library contains utility functions you need for comfortable development. These are such functions for collections manipulations, files, streams and so on.
In theory you can use just runtime but you generally shouldn't because there are no standard library in it so you will lose many utility functions required for comfortable development (such as map, filter, toList and so on) so I don't think you should.
So in fact you need both. If you need make the result package smaller then you can process you app with proguard.
Update
Starting from Kotlin 1.2, kotlin-runtime and kotlin-stdlib are merged into single artifact kotlin-stdlib.
We merge kotlin-runtime and kotlin-stdlib into the single artifact kotlin-stdlib. Also we’re going to rename kotlin-runtime.jar, shipped in the compiler distribution, to kotlin-stdlib.jar, to reduce the amount of confusion caused by having differently named standard library in different build systems.
That rename will happen in two stages: in 1.1 there will be both kotlin-runtime.jar and kotlin-stdlib.jar with the same content in the compiler distribution, and in 1.2 the former will be removed.
Refer to Kotlin 1.1: What’s coming in the standard library for details.

AspectJ - compile time - Weave types int JDK classes

I need to add fields into JDK Classes. e.g java.lang.String
First I tried:
declare parents: ( * && !java.lang.Object ) implements VistaInt;
public String[] VistaInt.abc;
this however doesn't work.
It throws a warning
this affected type is not exposed to the weaver:
org.aspectj.lang.Signature [Xlint:typeNotExposedToWeaver]
So I researched it on internet and find out, that it is harder as it seems to be and
AspectJ doesn't support intrumenting JDK classes directly says here:
http://www.inf.usi.ch/faculty/binder/documents/pppj08.pdf
But there is proposed something callse FERRARI framework, tool for AspectJ that should allow injecting JDK classes.
So I kept searching for it and get here:
http://dev.eclipse.org/mhonarc/lists/aspectj-dev/msg02520.html
But none of these links work and I was not able to find any other source, or tool or anything that would help me.
Do you have any idea, where to find this library, or how to inject java JDK types??
Thank you!
First you need to locate the rt.jar that your Eclipse project is using. This is most likely the default for your machine but to check you can right-click on the JRE system library icon in your project, click on Properties and Installed JREs. The rt.jar file is under lib.
Once you have it you will need to weave it from the command line (you might need to download separate ajc compiler). Say you want to weave MyAspect.aj you would run
ajc -inpath rt.jar MyAspect.aj -outjar newrt.jar
You then need to make sure that your code uses this library by putting newrt.jar on the bootclasspath ahead of rt.jar. Running from the command line you do this
java -Xbootclasspath/<path to newrt.jar> MyApplication
In Eclsipse you add -Xbootclasspath/<path to newrt.jar> to the Run configuration.
However, I would not recommend modifying java.lang.String as JVMs often treat this class specially. But you can give it a go if you want :)
Note
I believe that the FERRARI framework that you refer to is for LTW (Load Time Weaving) and this discussion has been for a CTW (Compile Time Weaving) solution. If you want to do LTW then you're going to have difficulties as custom class loaders can't load java.* classes so you can't weave these at load time. Your link suggests that people have attempted a workaround but I don't know anything about this.

Code recognition by JVM

Will there be any difference in the bytecode or the compiled code using different JDKs(eg: 1.4 & 1.5 in this case). If so, how would a JVM recognize and address it at runtime?
The class file format has version information in it.
See the Java class file format. The major_version and minor_version fields are used to differentiate different versions of class files.
And yes, there can be differences. For instance, JDK1.4 didn't support generics. It couldn't load classes that contain them (produced by a 1.5 compiler).