I wounder, why I get an exception. I'm using the Eclipse plugin 2.1.3.
Example code: package test; object test { class A(as: Array[S]) case class S(s: String) def main(args: Array[String]): Unit = { Console.println(new A(Array())) } } Error message: Exception in thread "main" java.lang.ClassNotFoundException: test/test$S at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:169) at scala.runtime.BoxedAnyArray.unbox(BoxedAnyArray.scala:150) at scala.runtime.ScalaRunTime$.arrayValue(ScalaRunTime.scala:107) at test.test$.main(test.scala:8) at test.test.main(test.scala) I decompiled the generated code and it looks like Object obj = ScalaRunTime$.MODULE$.arrayValue( Predef$.MODULE$.Array( new BoxedObjectArray((Object[])new test.S[0])), "test.test$S"); test.A a = new test.A((test.S[])( (obj instanceof BoxedArray) ? ScalaRunTime$.MODULE$.arrayValue((BoxedArray)obj, "test.test$S") : obj)); Console$.MODULE$.println(a); Line 150 of BoxedAnyArray.scala is unboxed = java.lang.reflect.Array.newInstance( Class.forName(elemTag), length); which also looks good. I tried the Eclipse-compiled code with scala 2.1.3 from sbaz and that worked just fine. -- Stefan Matthias Aust |
In general it does work to create a class in the plugin and then run
it directly from Eclipse. Can you describe the sequence you tried in more detail? Incidentally, the easiest thing to do is to create the class using "New -> Scala Application" instead of "New -> Scala Object". If you do it that way, the plugin will create a run profile for you automatically. -Lex |
Lex Spoon schrieb:
> In general it does work to create a class in the plugin and then run > it directly from Eclipse. [...] Not for my example... because that is what I did. I just tried it also with a fresh Eclipse 3.2 RC1 plus plugin 2.3.1 and got the same effect. The java.class.path accordingly to the System property is "$ECLIPSE\plugins\ch.epfl.lamp.sdt.compiler_2.1.2.7046\lib\scala-library.jar;C:\Dokumente und Einstellungen\sma\workspace\scala\bin" (with $ECLIPSE expanded of course) and that looks perfectly okay. And if I run the example via the command line version of scala, it works. -- Stefan Matthias Aust |
In reply to this post by Stefan Matthias Aust
Hi Stefan,
Ah! This bug is so wicked. The following code works until the last line: package test; object test { class A(as: Array[S]) case class S(s: String) def main(args : Array[String]) : Unit = { Console.println("hello world"); val xxx = S("hello"); Console.println(xxx.s); val clazz = Class.forName("test.test$S"); Console.println("clazz: " + clazz); val unbox = java.lang.reflect.Array.newInstance(clazz, 10); Console.println("array: " + unbox); // crash: next line Console.println(new A(Array())) } } And the reason why: the JDT launcher loads library classes from a different more privledged class loader than the application. This means that the code in the library will load only from the library's class loader and not the application's, which means our use of reflection to get at application classes in the Scala run-time will not work with the JDT launcher. Actually this is a pretty common setup for security reasons as far as I understand it (prevents trojan string attacks: its probably true in web browsers - should test). When invoked from the command line, the Scala library is treated like part of the application rather than a privledged system library, so it is loaded from the application's class loader and hence forName between the library and the application will behave the same. In Eclipse, this isn't true, and as a result we get a crash. As for the fix, I think we shouldn't depend on the Scala library and application class loaders being the same. But we are going to have to Thanks for finding this! Sean Stefan Matthias Aust wrote: > I wounder, why I get an exception. I'm using the Eclipse plugin 2.1.3. > > Example code: > > package test; > > object test { > class A(as: Array[S]) > case class S(s: String) > > def main(args: Array[String]): Unit = { > Console.println(new A(Array())) > } > } > > Error message: > > Exception in thread "main" java.lang.ClassNotFoundException: test/test$S > at java.lang.Class.forName0(Native Method) > at java.lang.Class.forName(Class.java:169) > at scala.runtime.BoxedAnyArray.unbox(BoxedAnyArray.scala:150) > at scala.runtime.ScalaRunTime$.arrayValue(ScalaRunTime.scala:107) > at test.test$.main(test.scala:8) > at test.test.main(test.scala) > > I decompiled the generated code and it looks like > > Object obj = ScalaRunTime$.MODULE$.arrayValue( > Predef$.MODULE$.Array( > new BoxedObjectArray((Object[])new test.S[0])), "test.test$S"); > test.A a = new test.A((test.S[])( > (obj instanceof BoxedArray) > ? ScalaRunTime$.MODULE$.arrayValue((BoxedArray)obj, "test.test$S") > : obj)); > Console$.MODULE$.println(a); > > Line 150 of BoxedAnyArray.scala is > > unboxed = java.lang.reflect.Array.newInstance( > Class.forName(elemTag), length); > > which also looks good. > > I tried the Eclipse-compiled code with scala 2.1.3 from sbaz and that > worked just fine. > |
Free forum by Nabble | Edit this page |