nraychaudhuri / scala-remote-repl

Connect a Scala REPL to running Play/Scala processes
24 stars 2 forks source link

First sample run fails, OSX, Java 1.7.0_51 #1

Open lutnos opened 10 years ago

lutnos commented 10 years ago

My first attempt to run the repo has failed with an apparent class loader issue.

First I download and build the remote repo project:

Last login: Wed Mar 12 15:40:28 on ttys008
davesimac:~ dave$ java -version
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)
davesimac:~ dave$ mkdir srr
davesimac:~ dave$ cd srr
davesimac:srr dave$ git clone https://github.com/nraychaudhuri/scala-remote-repl
Cloning into 'scala-remote-repl'...
remote: Reusing existing pack: 110, done.
remote: Total 110 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (110/110), 48.96 KiB | 0 bytes/s, done.
Resolving deltas: 100% (21/21), done.
Checking connectivity... done.
davesimac:srr dave$ cd scala-remote-repl/
davesimac:scala-remote-repl dave$ sbt publishLocal
Loading /Users/dave/sbt/0.13.0/sbt/bin/sbt-launch-lib.bash
[info] Loading global plugins from /Users/dave/.sbt/0.13/plugins
[info] Loading project definition from /Users/dave/srr/scala-remote-repl/project
[info] Updating {file:/Users/dave/srr/scala-remote-repl/project/}scala-remote-repl-build...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Set current project to remote-repl (in build file:/Users/dave/srr/scala-remote-repl/)
[info] Packaging /Users/dave/srr/scala-remote-repl/target/scala-2.10/remote-repl_2.10-0.1-SNAPSHOT-sources.jar ...
[info] Packaging /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/agent_2.10-0.1-SNAPSHOT-sources.jar ...
[info] Updating {file:/Users/dave/srr/scala-remote-repl/}main...
[info] Done packaging.
[info] Updating {file:/Users/dave/srr/scala-remote-repl/}agent...
[info] Done packaging.
[info] Wrote /Users/dave/srr/scala-remote-repl/target/scala-2.10/remote-repl_2.10-0.1-SNAPSHOT.pom
[info] Wrote /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/agent_2.10-0.1-SNAPSHOT.pom
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Resolving org.scala-lang#scala-reflect;2.10.2 ...
[info] Main Java API documentation to /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/api...
[info] Compiling 2 Java sources to /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/classes...
[info] Resolving com.typesafe#config;1.2.0 ...
[info] Done updating.
[info] :: delivering :: agent#agent_2.10;0.1-SNAPSHOT :: 0.1-SNAPSHOT :: integration :: Wed Mar 12 15:46:44 GMT 2014
[info]  delivering ivy file to /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/ivy-0.1-SNAPSHOT.xml
[info] :: delivering :: net.nworks#remote-repl_2.10;0.1-SNAPSHOT :: 0.1-SNAPSHOT :: integration :: Wed Mar 12 15:46:44 GMT 2014
[info]  delivering ivy file to /Users/dave/srr/scala-remote-repl/target/scala-2.10/ivy-0.1-SNAPSHOT.xml
[info] Main Scala API documentation to /Users/dave/srr/scala-remote-repl/target/scala-2.10/api...
[info] Compiling 3 Scala sources to /Users/dave/srr/scala-remote-repl/target/scala-2.10/classes...
[warn] Note: /Users/dave/srr/scala-remote-repl/agent/src/main/java/com/nworks/remote/agent/AgentMain.java uses unchecked or unsafe operations.
[warn] Note: Recompile with -Xlint:unchecked for details.
[info] Loading source file /Users/dave/srr/scala-remote-repl/agent/src/main/java/com/nworks/remote/agent/AgentMain.java...
[info] Loading source file /Users/dave/srr/scala-remote-repl/agent/src/main/java/com/nworks/remote/agent/ClassLoaderFinder.java...
[info] Constructing Javadoc information...
[info] Standard Doclet version 1.7.0_51
[info] Building tree for all the packages and classes...
[info] Generating /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/api/com/nworks/remote/agent/AgentMain.html...
[info] Generating /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/api/com/nworks/remote/agent/ClassLoaderFinder.html...
[info] Generating /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/api/com/nworks/remote/agent/package-frame.html...
[info] Generating /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/api/com/nworks/remote/agent/package-summary.html...
[info] Generating /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/api/com/nworks/remote/agent/package-tree.html...
[info] Generating /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/api/constant-values.html...
[info] Building index for all the packages and classes...
[info] Generating /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/api/overview-tree.html...
[info] Generating /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/api/index-all.html...
[info] Generating /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/api/deprecated-list.html...
[info] Building index for all classes...
[info] Generating /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/api/allclasses-frame.html...
[info] Generating /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/api/allclasses-noframe.html...
[info] Generating /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/api/index.html...
[info] Generating /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/api/help-doc.html...
[info] Main Java API documentation successful.
[info] Packaging /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/agent_2.10-0.1-SNAPSHOT-javadoc.jar ...
[info] Packaging /Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/agent_2.10-0.1-SNAPSHOT.jar ...
[info] Done packaging.
[info] Done packaging.
[info]  published agent_2.10 to /Users/dave/.ivy2/local/agent/agent_2.10/0.1-SNAPSHOT/poms/agent_2.10.pom
[info]  published agent_2.10 to /Users/dave/.ivy2/local/agent/agent_2.10/0.1-SNAPSHOT/jars/agent_2.10.jar
[info]  published agent_2.10 to /Users/dave/.ivy2/local/agent/agent_2.10/0.1-SNAPSHOT/srcs/agent_2.10-sources.jar
[info]  published agent_2.10 to /Users/dave/.ivy2/local/agent/agent_2.10/0.1-SNAPSHOT/docs/agent_2.10-javadoc.jar
[info]  published ivy to /Users/dave/.ivy2/local/agent/agent_2.10/0.1-SNAPSHOT/ivys/ivy.xml
model contains 12 documentable templates
[info] Main Scala API documentation successful.
[warn] there were 1 deprecation warning(s); re-run with -deprecation for details
[warn] one warning found
[info] Packaging /Users/dave/srr/scala-remote-repl/target/scala-2.10/remote-repl_2.10-0.1-SNAPSHOT-javadoc.jar ...
[info] Packaging /Users/dave/srr/scala-remote-repl/target/scala-2.10/remote-repl_2.10-0.1-SNAPSHOT.jar ...
[info] Done packaging.
[info] Done packaging.
[info]  published remote-repl_2.10 to /Users/dave/.ivy2/local/net.nworks/remote-repl_2.10/0.1-SNAPSHOT/poms/remote-repl_2.10.pom
[info]  published remote-repl_2.10 to /Users/dave/.ivy2/local/net.nworks/remote-repl_2.10/0.1-SNAPSHOT/jars/remote-repl_2.10.jar
[info]  published remote-repl_2.10 to /Users/dave/.ivy2/local/net.nworks/remote-repl_2.10/0.1-SNAPSHOT/srcs/remote-repl_2.10-sources.jar
[info]  published remote-repl_2.10 to /Users/dave/.ivy2/local/net.nworks/remote-repl_2.10/0.1-SNAPSHOT/docs/remote-repl_2.10-javadoc.jar
[info]  published ivy to /Users/dave/.ivy2/local/net.nworks/remote-repl_2.10/0.1-SNAPSHOT/ivys/ivy.xml
[success] Total time: 9 s, completed 12-Mar-2014 15:46:52
davesimac:scala-remote-repl dave$ vi davejars.conf
davesimac:scala-remote-repl dave$ cat davejars.conf 
repl.agent.path=/Users/dave/srr/scala-remote-repl/agent/target/scala-2.10/agent_2.10-0.1-SNAPSHOT.jar
repl.scala.compiler.path=/Users/dave/.ivy2/cache/org.scala-lang/scala-compiler/jars/scala-compiler-2.10.2.jar
repl.server.path=/Users/dave/srr/scala-remote-repl/target/scala-2.10/remote-repl_2.10-0.1-SNAPSHOT.jar
davesimac:scala-remote-repl dave$ 

Then in a separate terminal window I start the sample play application:

Last login: Wed Mar 12 15:43:16 on ttys009
davesimac:~ dave$ pwd
/Users/dave
davesimac:~ dave$ cd srr
davesimac:srr dave$ cd scala-remote-repl/
davesimac:scala-remote-repl dave$ ls
README.md   build.sbt   myjars.conf sample_play_app target
agent       davejars.conf   project     src
davesimac:scala-remote-repl dave$ cd sample_play_app/
davesimac:sample_play_app dave$ ls
README      build.sbt   project     test
app     conf        public
davesimac:sample_play_app dave$ cat README 
This is your new Play application
=====================================

This file will be packaged with your application, when using `play dist`.
davesimac:sample_play_app dave$ sbt
Loading /Users/dave/sbt/0.13.0/sbt/bin/sbt-launch-lib.bash
[info] Loading global plugins from /Users/dave/.sbt/0.13/plugins
[info] Updating {file:/Users/dave/.sbt/0.13/plugins/}global-plugins...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Loading project definition from /Users/dave/srr/scala-remote-repl/sample_play_app/project
[info] Set current project to sample_play_app (in build file:/Users/dave/srr/scala-remote-repl/sample_play_app/)
[sample_play_app] $ run
[info] Updating {file:/Users/dave/srr/scala-remote-repl/sample_play_app/}sample_play_app...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] downloading http://repo.typesafe.com/typesafe/releases/com/typesafe/play/anorm_2.10/2.2.2/anorm_2.10-2.2.2.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#anorm_2.10;2.2.2!anorm_2.10.jar (944ms)
[info] downloading http://repo.typesafe.com/typesafe/releases/com/typesafe/play/play-cache_2.10/2.2.2/play-cache_2.10-2.2.2.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#play-cache_2.10;2.2.2!play-cache_2.10.jar (466ms)
[info] Done updating.

--- (Running the application from SBT, auto-reloading is enabled) ---

[info] play - Listening for HTTP on /0:0:0:0:0:0:0:0:9000

(Server started, use Ctrl+D to stop and go back to the console...)

[info] Compiling 3 Scala sources and 1 Java source to /Users/dave/srr/scala-remote-repl/sample_play_app/target/scala-2.10/classes...
[info] play - Application started (Dev)
objc[6005]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/bin/java and /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.

Finally trying to invoke the remote repo:

davesimac:scala-remote-repl dave$ ps -ef |grep [j]ava
  501  4367  4308   0  2:37pm ttys001    3:03.03 /usr/bin/java -Xms1024m -Xmx1024m -XX:MaxPermSize=256m -XX:ReservedCodeCacheSize=128m -jar /Users/dave/sbt/0.13.0/sbt/bin/sbt-launch.jar
  501  6005  5946   0  3:53pm ttys010    1:05.03 /usr/bin/java -Xms1024m -Xmx1024m -XX:MaxPermSize=256m -XX:ReservedCodeCacheSize=128m -jar /Users/dave/sbt/0.13.0/sbt/bin/sbt-launch.jar
davesimac:scala-remote-repl dave$ sbt -Dconfig.file=davejars.conf "run 6005 127.0.0.1 9191"
Loading /Users/dave/sbt/0.13.0/sbt/bin/sbt-launch-lib.bash
[info] Loading global plugins from /Users/dave/.sbt/0.13/plugins
[info] Loading project definition from /Users/dave/srr/scala-remote-repl/project
[info] Set current project to remote-repl (in build file:/Users/dave/srr/scala-remote-repl/)
[info] Running com.nworks.remote.repl.Main 6005 127.0.0.1 9191
Connect to 127.0.0.1:9191?[Hit enter for yes]

Provokes this error in the play application:

Running agent in remote jvm...
Selected classloader sun.misc.Launcher$AppClassLoader@18fb53f6
Resetting the classloader...sun.misc.Launcher$AppClassLoader@18fb53f6
Exception in thread "remote-repl-thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at com.nworks.remote.agent.AgentMain.startRepl(AgentMain.java:82)
    at com.nworks.remote.agent.AgentMain.access$100(AgentMain.java:11)
    at com.nworks.remote.agent.AgentMain$1.run(AgentMain.java:36)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.nworks.remote.agent.AgentMain.startRepl(AgentMain.java:78)
    ... 2 more
Caused by: java.lang.NoClassDefFoundError: scala/collection/Seq
    at com.nworks.remote.repl.ServerRepl.start(ServerRepl.scala)
    ... 7 more
Caused by: java.lang.ClassNotFoundException: scala.collection.Seq
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 8 more

and this in the remote repo invocation:

[error] (run-main-0) java.net.ConnectException: Connection refused
java.net.ConnectException: Connection refused
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:579)
    at java.net.Socket.connect(Socket.java:528)
    at java.net.Socket.(Socket.java:425)
    at java.net.Socket.(Socket.java:208)
    at com.nworks.remote.repl.ClientRepl$.connectToRemote(ClientRepl.scala:17)
    at com.nworks.remote.repl.Main$.main(Main.scala:19)
    at com.nworks.remote.repl.Main.main(Main.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
[trace] Stack trace suppressed: run last main/compile:run for the full output.
java.lang.RuntimeException: Nonzero exit code: 1
    at scala.sys.package$.error(package.scala:27)
[trace] Stack trace suppressed: run last main/compile:run for the full output.
[error] (main/compile:run) Nonzero exit code: 1
[error] Total time: 281 s, completed 12-Mar-2014 16:04:28
davesimac:scala-remote-repl dave$

Please let me know if I can do anything further to investigate this, or otherwise how I might get this very useful project working.

Thanks

Dave

nraychaudhuri commented 10 years ago

I see you are running the Play application in "dev" mode using sbt run. One of the limitation of the remote-repl tool (which I am planning to fix as soon as possible) is doesn't work very well if you have multiple classloaders. When you run Play in dev mode we have to deal with sbt classloaders, play classloaders and others. If you run Play using "start" (in prod mode) it should work.

One possible way to fix this problem would be to show user all the available classloaders and tool latch on to the one selected. This is pretty high in my list. I might work on this weekend.

lutnos commented 10 years ago

Thanks for explaining, I had previously assumed that your reference in the video to use in production mode was solely a strength, rather than a possible source of weakness. Now I understand, I can move forwards

Yes, I now have it working using production mode

davesimac:sample_play_app dave$ ~/play/play-2.2.1/play start
[info] Loading global plugins from /Users/dave/.sbt/0.13/plugins
[info] Loading project definition from /Users/dave/srr/scala-remote-repl/sample_play_app/project
This project uses Play 2.2.2!
Update the Play sbt-plugin version to 2.2.1 (usually in project/plugins.sbt)

[info] Set current project to sample_play_app (in build file:/Users/dave/srr/scala-remote-repl/sample_play_app/)
(Starting server. Type Ctrl+D to exit logs, the server will remain in background)
Play server process ID is 13060
[info] play - Application started (Prod)
[info] play - Listening for HTTP on /0:0:0:0:0:0:0:0:9000
objc[13060]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/bin/java and /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.
Running agent in remote jvm...
Selected classloader sun.misc.Launcher$AppClassLoader@23b561a2
Waiting for connection at 9191
davesimac:scala-remote-repl dave$ sbt -Dconfig.file=davejars.conf "run 13060 127.0.0.1 9191"
Loading /Users/dave/sbt/0.13.0/sbt/bin/sbt-launch-lib.bash
[info] Loading global plugins from /Users/dave/.sbt/0.13/plugins
[info] Loading project definition from /Users/dave/srr/scala-remote-repl/project
[info] Set current project to remote-repl (in build file:/Users/dave/srr/scala-remote-repl/)
[info] Running com.nworks.remote.repl.Main 13060 127.0.0.1 9191
Connect to 127.0.0.1:9191?[Hit enter for yes]
Connected to remote REPL. Fire up your commands
Welcome to Scala version 2.10.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_51).
Type in expressions to have them evaluated.
Type :help for more information.
Welcome to Remote REPL. Enjoy!
scala> import play.api.Play.current
import play.api.Play.current
scala> import play.api.cache.Cache
import play.api.cache.Cache
scala> Cache.set("dave", "from remore repl")
scala> 

I look forward to future developments

andreak commented 10 years ago

I tried to attach to a Tomcat-app, and it didn't work, probably due to class-loader issues: Error in tomcat-log:

Running agent in remote jvm...
Selected classloader sun.misc.Launcher$AppClassLoader@44f757b9
Resetting the classloader...sun.misc.Launcher$AppClassLoader@44f757b9
Exception in thread "remote-repl-thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
        at com.nworks.remote.agent.AgentMain.startRepl(AgentMain.java:82)
        at com.nworks.remote.agent.AgentMain.access$100(AgentMain.java:11)
        at com.nworks.remote.agent.AgentMain$1.run(AgentMain.java:36)
Caused by: java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.nworks.remote.agent.AgentMain.startRepl(AgentMain.java:78)
        ... 2 more
Caused by: java.lang.NoClassDefFoundError: scala/collection/Seq
        at com.nworks.remote.repl.ServerRepl.start(ServerRepl.scala)
        ... 7 more
Caused by: java.lang.ClassNotFoundException: scala.collection.Seq
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
        ... 8 more

Also, I had to make minor tweaks to build.sbt to make it work with Scala-2.11.2:

import sbt.Keys._

name := "remote-repl"

organization := "net.nworks"

val agent = project.in(file("agent")).settings(
  packageOptions in (Compile, packageBin) +=
    Package.ManifestAttributes("Agent-Class" -> "com.nworks.remote.agent.AgentMain" ),
  scalaVersion := "2.11.2"
)

val main = project.in(file(".")).aggregate(agent).settings(
  unmanagedJars in Compile ~= {uj =>
    Seq(Attributed.blank(file(System.getProperty("java.home").dropRight(3)+"lib/tools.jar"))) ++ uj
  },
  libraryDependencies ++= Seq(
    "org.scala-lang" % "scala-compiler" % scalaVersion.value,
    "jline" % "jline" % "2.11",
    "com.typesafe" % "config" % "1.2.0"
  ),
  scalaVersion := "2.11.2"
)

And some minor changes to ClientRepl (change jline imports and fix constructor-call to ConsoleReader

Are there any plans to port this to Scala-2.11 and fix the class-loader issue?

Thanks!

nraychaudhuri commented 10 years ago

Yeah. Its a classloader issue. I actually have this in my todo list. Since I am getting few requests to fix this I will try to take out some time and implement this. One possible way to do this would be to show user all the available classloaders so that user can pick one hook into.

joprice commented 9 years ago

+1