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

Installation problem #15

Closed
MarcinMoskala opened this issue Feb 28, 2017 · 14 comments
Closed

Installation problem #15

MarcinMoskala opened this issue Feb 28, 2017 · 14 comments

Comments

@MarcinMoskala
Copy link
Contributor

Hey, I installed it on mac exactly like in instructions. Not in /bin because it is not permitted in new mac, but in another folder and I added it to PATH, but when I start any script using kscript I get:

Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/script/templates/standard/ScriptTemplateWithArgs
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at Main_Hello.main(Main_Hello.java:4)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.jetbrains.kotlin.runner.AbstractRunner.run(runners.kt:60)
	at org.jetbrains.kotlin.runner.Main.run(Main.kt:104)
	at org.jetbrains.kotlin.runner.Main.main(Main.kt:110)
Caused by: java.lang.ClassNotFoundException: kotlin.script.templates.standard.ScriptTemplateWithArgs
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 19 more
@holgerbrandl
Copy link
Collaborator

Sorry for inconvenience. What version of kotlin are you using? Just type

 kotlinc -version

@MarcinMoskala
Copy link
Contributor Author

MBP-MarcinMac:~ marcin$ kotlinc -version
info: Kotlin Compiler version 1.1.0-rc-91

@holgerbrandl
Copy link
Collaborator

Indeed kscript is not yet working with 1.1. Unfortunately this seems more an issue with Kotlin itself, and I have filed a ticket for the problem:
https://youtrack.jetbrains.com/issue/KT-16562

Feel welcome to vote for it, because JB is more likely to act upon it if there are some votes.

@holgerbrandl
Copy link
Collaborator

They suggested a workaround and I will release a patched version of kscript later today or tomorrow.

@holgerbrandl
Copy link
Collaborator

I've released kscript v1.2 this morning which should solve the problem. You can run the auto-update with

kscript --self-update

Feel welcome if you have other issues when using kscript

@chocolateboy
Copy link

chocolateboy commented Apr 15, 2017

I'm getting the same error on Linux:

kscript: 1.2 (15c7cc4)
kotlin: 1.1.1
OS: Linux (Arch)

$ kscript --clear-cache
Cleaning up cache...
$ cat hello.kt
println("Hello, world!")
$ kscript hello.kt
Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/script/templates/standard/ScriptTemplateWithArgs
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at Main_Kscript_stdin_e159f6.main(Main_Kscript_stdin_e159f6.java:4)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.jetbrains.kotlin.runner.AbstractRunner.run(runners.kt:60)
	at org.jetbrains.kotlin.runner.Main.run(Main.kt:104)
	at org.jetbrains.kotlin.runner.Main.main(Main.kt:110)
Caused by: java.lang.ClassNotFoundException: kotlin.script.templates.standard.ScriptTemplateWithArgs
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 19 more

kotlinc is installed correctly and working OK.

@chocolateboy
Copy link

I see the fix makes use of KOTLIN_HOME. It's not set on my system, but setting it fixes the problem:

$ KOTLIN_HOME=/usr/share/kotlin kscript hello.kt
Hello, world!

It could be a safe default if it's not defined:

-exec kotlin ${kotlin_opts} -classpath ${jarFile}:${KOTLIN_HOME}/lib/kotlin-script-runtime.jar:"$classpath" Main_${className} "$@"
+exec kotlin ${kotlin_opts} -classpath ${jarFile}:${KOTLIN_HOME:-/usr/share/kotlin}/lib/kotlin-script-runtime.jar:"$classpath" Main_${className} "$@"

Alternatively, you could adopt the same approach as kotlin-script.

Or possibly even scrape it out of kotlinc e.g.:

$ JAVACMD=echo kotlin
-Xmx256M -Xms32M -Dkotlin.home=/usr/share/kotlin -cp /usr/share/kotlin/lib/kotlin-runner.jar org.jetbrains.kotlin.runner.Main

@holgerbrandl
Copy link
Collaborator

Thanks for the hint.

@chocolateboy
Copy link

Thanks, but that particular solution doesn't work on my system:

$ KOTLIN_HOME="$(dirname $(which kotlinc))/.." 
$ readlink -f $KOTLIN_HOME
/usr

That means it looks for the JAR in:

$ echo ${KOTLIN_HOME}/lib/kotlin-script-runtime.jar
/usr/lib/kotlin-script-runtime.jar

Rather than where it actualy resides:

/usr/share/kotlin/lib/kotlin-script-runtime.jar

Like I say, the correct path can be exposed by the kotlinc script (or its kotlin wrapper) if you don't mind doing a bit of light scraping:

$ JAVACMD=echo kotlin
-Xmx256M -Xms32M -Dkotlin.home=/usr/share/kotlin -cp /usr/share/kotlin/lib/kotlin-runner.jar org.jetbrains.kotlin.runner.Main

@holgerbrandl
Copy link
Collaborator

Just out of curiosity. How did kotlin end up under /usr/share/? homebrew? I always use sdkman which just dumps it in a hidden directory in the user home.

I'd think it would be better to avoid another JVM launch (which costs another few hundred milliseconds). Especially for small inlined command-line tools this may make a difference for some users.

So what about (see also latest commit):

if [[ $OSTYPE != darwin* ]]; then minusFarg="-f"; fi
abspath() { echo "$(readlink ${minusFarg} $1)"; }
ll $(dirname $(abspath $(which kotlinc)))/../lib/kotlin-script-runtime.jar

@chocolateboy
Copy link

chocolateboy commented Apr 18, 2017

Just out of curiosity. How did kotlin end up under /usr/share/

It's the standard location for application data on Arch Linux.

I'd think it would be better to avoid another JVM launch (which costs another few hundred milliseconds).

It doesn't launch the JVM:

$ time KOTLIN_RUNNER=1 JAVACMD=echo kotlinc
real	0m0.012s
user	0m0.000s
sys	0m0.000s

So what about (see also latest commit):

ls: cannot access '/usr/bin/../lib/kotlin-script-runtime.jar': No such file or directory

@holgerbrandl
Copy link
Collaborator

holgerbrandl commented Apr 18, 2017

Thanks for your patience. Could you try again. I've changed it to

    KOTLIN_HOME=$(dirname $(dirname $(JAVACMD=echo kotlin  |  awk 'NR>1' RS=' ' | grep kotlin-runner)))

I'm still confused/amazed by JAVACMD=echo kotlin. It looks like a variable assignment but it somehow resolves kotlin?

@chocolateboy
Copy link

chocolateboy commented Apr 18, 2017

Could you try again.

Yes, that works. Thanks!

I'm still confused/amazed by JAVACMD=echo kotlin. It looks like a variable assignment but it somehow resolves kotlin?

It's just an environment variable assignment, the same as running:

env JAVACMD=echo kotlin

or setting:

JAVACMD=echo

in kotlinc.

The kotlin wrapper sets KOTLIN_RUNNER=1, which selects a branch at the end of kotlinc, which defines java_args, which defines the kotlin.home property. On my system, it's faster to run kotlinc directly as suggested above:

$ time JAVACMD=echo kotlin
real	0m0.019s
user	0m0.000s
sys	0m0.000s

$ time KOTLIN_RUNNER=1 JAVACMD=echo kotlinc
real	0m0.012s
user	0m0.000s
sys	0m0.000s

kotlinc allows the path to java to be supplied via the JAVACMD environment variable:

"${JAVACMD:=java}" $JAVA_OPTS "${java_args[@]}" -cp "${kotlin_app[@]}" "${kotlin_args[@]}"

If not supplied it defaults to java. We abuse this to replace java with echo, so the last line of kotlinc becomes:

echo $JAVA_OPTS "${java_args[@]}" -cp "${kotlin_app[@]}" "${kotlin_args[@]}"

This prints out the kotlin.home property via java_args:

    java_args=("${java_args[@]}" "-Dkotlin.home=${KOTLIN_HOME}")

IMO, it's safer to just use the defined kotlin.home property rather than scraping the name of a JAR file, which might be removed/renamed. Putting this together gives:

$ KOTLIN_HOME=$(KOTLIN_RUNNER=1 JAVACMD=echo kotlinc | awk 'NR>1' RS=' ' | grep -F kotlin.home= | cut -d= -f2)
$ echo $KOTLIN_HOME
/usr/share/kotlin

@holgerbrandl
Copy link
Collaborator

Thanks for the nice explanation. I've changed it accordingly.

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

No branches or pull requests

3 participants