- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Change of behaviour between Scala2.[7-8] and 2.9 when using Java Agents
Sat, 2011-07-09, 11:28
Hi,
I tried sending this to Scala users and got no takers, so given it is
related to the internals of the system I thought I would give this list
a try. I hope this is ok.
I have a problem with a change in the behaviour of Scala between version
2.9 and the earlier versions, and am hoping someone can save me some
time by pointing me in the correct direction for solving it.
I'm building various Transactional Memory solutions for Scala. These are
based on the Deuce STM approach of using Java Agents to perform a byte
code rewrite at run time. This rewrite creates instrumented duplicates
of the methods that appear in the classes. These duplicates can then be
used to execute sections of code transactionally. This is done in
conjunction with additionally created classes that hold information
about the positions of fields within the original classes.
So far so good, and this all works fine with Scala 2.7 and 2.8, the
problems arises with Scala 2.9. When trying to use this system under 2.9
the program fails with depending on which of my TM set-ups I'm using a
field or a method not found exception. In both cases these are fields or
methods that should have been added by the Java Agent. It would appear
that the code that the JVM is seeing at this point has not been extended
by the Java Agent. The addition of print statements confirms that the
Java Agent is running for the classes required. The fact that the
program is trying to access the fields that are only inserted by the
Java Agent shows that at least some of the rewritten code is being
executed. Examining the compiled Scala code shows no obvious changes for
the files in question between 2.7 and 2.9. Running the Java Agent on the
code outside of the runtime environment produces the correct rewritten
code. All of these tests have been performed with the same JVM. Does
anyone have any thoughts on what has changed between 2.8 and 2.9 that
would cause this error? Is there some new verification of class signatures?
Many thanks in advance
Daniel
Mon, 2011-07-11, 15:37
#2
Re: Change of behaviour between Scala2.[7-8] and 2.9 when using
Hi Martin,
Thanks for getting back to me. My code does not use the Java Signature attribute, so I am relatively sure that this is no the cause. However I will keep narrowing this down and try to come back to you in with more specific questions. In the mean time if anyone else has any thoughts I would love to hear from you.
All the best
Daniel
On 09/07/11 13:19, martin odersky wrote:
Thanks for getting back to me. My code does not use the Java Signature attribute, so I am relatively sure that this is no the cause. However I will keep narrowing this down and try to come back to you in with more specific questions. In the mean time if anyone else has any thoughts I would love to hear from you.
All the best
Daniel
On 09/07/11 13:19, martin odersky wrote:
dhP8VCkidF9kdpy0w [at] mail [dot] gmail [dot] com" type="cite">One change which might be relevant is that Java generic signatures have changed between 2.8 and 2.9. 2.8 generated sometimes incorrect signatures for Java generics. These have changed in 2.9. So if you code depends on the JavaSignature attribute it needs to be updated.
Cheers
-- Martin
On Sat, Jul 9, 2011 at 12:28 PM, Daniel Goodman <goodmand [at] cs [dot] man [dot] ac [dot] uk" rel="nofollow">goodmand@cs.man.ac.uk> wrote:
Hi,
I tried sending this to Scala users and got no takers, so given it is related to the internals of the system I thought I would give this list a try. I hope this is ok.
I have a problem with a change in the behaviour of Scala between version 2.9 and the earlier versions, and am hoping someone can save me some time by pointing me in the correct direction for solving it.
I'm building various Transactional Memory solutions for Scala. These are based on the Deuce STM approach of using Java Agents to perform a byte code rewrite at run time. This rewrite creates instrumented duplicates of the methods that appear in the classes. These duplicates can then be used to execute sections of code transactionally. This is done in conjunction with additionally created classes that hold information about the positions of fields within the original classes.
So far so good, and this all works fine with Scala 2.7 and 2.8, the problems arises with Scala 2.9. When trying to use this system under 2.9 the program fails with depending on which of my TM set-ups I'm using a field or a method not found exception. In both cases these are fields or methods that should have been added by the Java Agent. It would appear that the code that the JVM is seeing at this point has not been extended by the Java Agent. The addition of print statements confirms that the Java Agent is running for the classes required. The fact that the program is trying to access the fields that are only inserted by the Java Agent shows that at least some of the rewritten code is being executed. Examining the compiled Scala code shows no obvious changes for the files in question between 2.7 and 2.9. Running the Java Agent on the code outside of the runtime environment produces the correct rewritten code. All of these tests have been performed with the same JVM. Does anyone have any thoughts on what has changed between 2.8 and 2.9 that would cause this error? Is there some new verification of class signatures?
Many thanks in advance
Daniel
--
Martin Odersky
Prof., EPFL and Chairman, Typesafe
PSED, 1015 Lausanne, Switzerland
Tel. EPFL: +41 21 693 6863
Tel. Typesafe: +41 21 691 4967
Wed, 2011-07-13, 16:57
#3
Re: Change of behaviour between Scala2.[7-8] and 2.9 when using
Hi,
So I am still trying to narrow down the cause of this issue. Experimenting with a specific case showed that running 2.8 or 2.9 code on the 2.9 version of scala throws a method not found exception when the code tried to access a new method added by the byte code rewrite. Running these versions against the 2.8 version of scala, the files compiled with the 2.8 version of scalac worked, but the ones compiled with the 2.9 version failed with a java.lang.NoClassDefFound Error. This appeared to be being thrown by the class loader. As this gave me a small piece of code to examine, where one version worked and one did not I decided to start examining the code here.
Examining the byte code shows that byte code instructions that make up the different methods are identical. This would appear to mean that it is the way the runtime environment uses the remaining meta-data in the class that is making the difference. To try and isolate this first I tried to strip back the command used in scala such that the code was running directly on the JVM rather than in an augmented runtime. However the closest I could get is as follows:
2.8
java -javaagent:muts_2.8.jar -cp /usr/scala-2.8.1.final/lib/scala-compiler.jar:/usr/scala-2.8.1.final/lib/scala-library.jar -Dscala.home=/usr/scala-2.8.1.final scala.tools.nsc.MainGenericRunner -cp .:./muts_2.8.jar ScalaHelloWorld
2.9
java -javaagent:muts_2.8.jar -cp muts_2.8.jar:. -Xbootclasspath/a:/usr/share/scala/lib/scala-library.jar ScalaHelloWorld
This would appear to show that Scala class files require an augmented runtime to execute. So the first questions are: Can I run scala code without either using an additional program or changing classes in the JVM? Secondly, in each of these cases what is the augmented functionality?
Next I looked at the fields in more detail: the code I compiled was:
import eu.teraflux.uniman.transactions.TMLib._
object ScalaHelloWorld2 {
def main(args:Array[String]) {
atomic{ Unit =>
println("Hello World from Scala")
}
}
}
which results in the three bytecode files being produced: ScalaHelloWorld2.class; ScalaHelloWorld2$.class and ScalaHelloWorld2$$anonfun$main$1.class. According to JavaP the differences between these classes are as follows.
ScalaHelloWorld2.class
2.8 contains
InnerClass:
public final #24= #21 of #23; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
which becomes
InnerClass:
public final #21; //class ScalaHelloWorld2$$anonfun$main$1
in 2.9.
The scala signatures are also different, 2.8 is
const #17 = Asciz 5:Q!\t\tcU2bYDU\r7p/>H\r\tqP3naRLhh9Q\"!A!A\t%cU2bYDU\r7p/>HQ!!5\tAB!A.8hy6bmL!!\r='.Z2u!\tb#D)!B:dC2BA-6-7b\nTWm;\te9A\rqJg.;?))\"\tiB7bS:$\"AHMyB)f.;\t\tZA\txm\t'2BA\t%O]1z!\t9#FQ%F!J,G-4\n-b#AB*ue&twM*);
and 2.9 is
const #17 = Asciz 5:Q!\t\tcU2bYDU\r7p/>H\r\tqP3naRLhh9Q\"!RA!M\r\1IK2dwnV8sY4cA%A1E)QBDYtwMCQM^1\nEa!AB(cUG-5\tACC8-7b\t9BCATGdm2kK$\"B\r\tQAj]&$hFar\"i-8y\tCA\n \tCCV]&$\"B1sON2a'\t)CCABeJ(U91KSQ\ta:fI4BA-FO]5oO*;
finally 2.8 also contains the following extra constant
const #24 = Asciz java/lang/Object;
ScalaHelloWorld2$.class
2.8 contains
InnerClass:
public final #41= #22 of #40; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
which becomes
InnerClass:
public final #22; //class ScalaHelloWorld2$$anonfun$main$1
in 2.9. 2.8 also contains the following extra constants
const #39 = Asciz ScalaHelloWorld2;
const #40 = class #39; // ScalaHelloWorld2
const #41 = Asciz $anonfun$main$1;
ScalaHelloWorld2$$anonfun$main$1.class
Finally
the 2.8 headers change from
InnerClass:
public final #51= #9 of #50; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
to
EnclosingMethod: length = 0x4
00 32 00 35
InnerClass:
public final #9; //class ScalaHelloWorld2$$anonfun$main$1
and the interface implemented changes from java.io.Serializable to scala.Serializable
I have included the full text of each of the methods at the end of the email incase I have missed out an important detail here. My last question is as my rewrite does not change any of these values, but augments the constant pool with additional values to support the additional instrumented methods, is anyone aware of what in these changes is causing the re-writen code to fail for the 2.9 code, but not for the 2.8 code?
Many thanks in advance
Daniel
ScalaHelloWorld2.class 2.8
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2 extends java.lang.Object
SourceFile: "ScalaHelloWorld2.scala"
ScalaSig: length = 0x3
05 00 00
RuntimeVisibleAnnotations: length = 0xB
00 01 00 0F 00 01 00 10 73 00 11
InnerClass:
public final #24= #21 of #23; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz main;
const #4 = Asciz ([Ljava/lang/String;)V;
const #5 = Asciz Code;
const #6 = Asciz ScalaHelloWorld2$;
const #7 = class #6; // ScalaHelloWorld2$
const #8 = Asciz MODULE$;
const #9 = Asciz LScalaHelloWorld2$;;
const #10 = NameAndType #8:#9;// MODULE$:LScalaHelloWorld2$;
const #11 = Field #7.#10; // ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
const #12 = NameAndType #3:#4;// main:([Ljava/lang/String;)V
const #13 = Method #7.#12; // ScalaHelloWorld2$.main:([Ljava/lang/String;)V
const #14 = Asciz ScalaSig;
const #15 = Asciz Lscala/reflect/ScalaSignature;;
const #16 = Asciz bytes;
const #17 = Asciz 5:Q!\t\tcU2bYDU\r7p/>H\r\tqP3naRLhh9Q\"!A!A\t%cU2bYDU\r7p/>HQ!!5\tAB!A.8hy6bmL!!\r='.Z2u!\tb#D)!B:dC2BA-6-7b\nTWm;\te9A\rqJg.;?))\"\tiB7bS:$\"AHMyB)f.;\t\tZA\txm\t'2BA\t%O]1z!\t9#FQ%F!J,G-4\n-b#AB*ue&twM*);
const #18 = Asciz RuntimeVisibleAnnotations;
const #19 = Asciz InnerClasses;
const #20 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #21 = class #20; // ScalaHelloWorld2$$anonfun$main$1
const #22 = Asciz ScalaHelloWorld2;
const #23 = class #22; // ScalaHelloWorld2
const #24 = Asciz $anonfun$main$1;
const #25 = Asciz java/lang/Object;
const #26 = class #25; // java/lang/Object
{
public static final void main(java.lang.String[]);
Code:
Stack=2, Locals=1, Args_size=1
0: getstatic #11; //Field ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
3: aload_0
4: invokevirtual #13; //Method ScalaHelloWorld2$.main:([Ljava/lang/String;)V
7: return
}
ScalaHelloWorld2.class 2.9
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2 extends java.lang.Object
SourceFile: "ScalaHelloWorld2.scala"
ScalaSig: length = 0x3
05 00 00
RuntimeVisibleAnnotations: length = 0xB
00 01 00 0F 00 01 00 10 73 00 11
InnerClass:
public final #21; //class ScalaHelloWorld2$$anonfun$main$1
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz main;
const #4 = Asciz ([Ljava/lang/String;)V;
const #5 = Asciz Code;
const #6 = Asciz ScalaHelloWorld2$;
const #7 = class #6; // ScalaHelloWorld2$
const #8 = Asciz MODULE$;
const #9 = Asciz LScalaHelloWorld2$;;
const #10 = NameAndType #8:#9;// MODULE$:LScalaHelloWorld2$;
const #11 = Field #7.#10; // ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
const #12 = NameAndType #3:#4;// main:([Ljava/lang/String;)V
const #13 = Method #7.#12; // ScalaHelloWorld2$.main:([Ljava/lang/String;)V
const #14 = Asciz ScalaSig;
const #15 = Asciz Lscala/reflect/ScalaSignature;;
const #16 = Asciz bytes;
const #17 = Asciz 5:Q!\t\tcU2bYDU\r7p/>H\r\tqP3naRLhh9Q\"!RA!M\r\1IK2dwnV8sY4cA%A1E)QBDYtwMCQM^1\nEa!AB(cUG-5\tACC8-7b\t9BCATGdm2kK$\"B\r\tQAj]&$hFar\"i-8y\tCA\n \tCCV]&$\"B1sON2a'\t)CCABeJ(U91KSQ\ta:fI4BA-FO]5oO*;
const #18 = Asciz RuntimeVisibleAnnotations;
const #19 = Asciz InnerClasses;
const #20 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #21 = class #20; // ScalaHelloWorld2$$anonfun$main$1
const #22 = Asciz ScalaHelloWorld2;
const #23 = class #22; // ScalaHelloWorld2
const #24 = Asciz java/lang/Object;
const #25 = class #24; // java/lang/Object
{
public static final void main(java.lang.String[]);
Code:
Stack=2, Locals=1, Args_size=1
0: getstatic #11; //Field ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
3: aload_0
4: invokevirtual #13; //Method ScalaHelloWorld2$.main:([Ljava/lang/String;)V
7: return
}
ScalaHelloWorld2$.class 2.8
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2$ extends java.lang.Object implements scala.ScalaObject
SourceFile: "ScalaHelloWorld2.scala"
Scala: length = 0x
InnerClass:
public final #41= #22 of #40; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz MODULE$;
const #4 = Asciz LScalaHelloWorld2$;;
const #5 = Asciz <clinit>;
const #6 = Asciz ()V;
const #7 = Asciz Code;
const #8 = Asciz ScalaHelloWorld2$;
const #9 = class #8; // ScalaHelloWorld2$
const #10 = Asciz <init>;
const #11 = NameAndType #10:#6;// "<init>":()V
const #12 = Method #9.#11; // ScalaHelloWorld2$."<init>":()V
const #13 = Asciz main;
const #14 = Asciz ([Ljava/lang/String;)V;
const #15 = Asciz eu/teraflux/uniman/transactions/TMLib$;
const #16 = class #15; // eu/teraflux/uniman/transactions/TMLib$
const #17 = Asciz Leu/teraflux/uniman/transactions/TMLib$;;
const #18 = NameAndType #3:#17;// MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
const #19 = Field #16.#18; // eu/teraflux/uniman/transactions/TMLib$.MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
const #20 = Asciz LineNumberTable;
const #21 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #22 = class #21; // ScalaHelloWorld2$$anonfun$main$1
const #23 = Method #22.#11; // ScalaHelloWorld2$$anonfun$main$1."<init>":()V
const #24 = Asciz atomic;
const #25 = Asciz (Lscala/Function1;)V;
const #26 = NameAndType #24:#25;// atomic:(Lscala/Function1;)V
const #27 = Method #16.#26; // eu/teraflux/uniman/transactions/TMLib$.atomic:(Lscala/Function1;)V
const #28 = Asciz this;
const #29 = Asciz args;
const #30 = Asciz [Ljava/lang/String;;
const #31 = Asciz LocalVariableTable;
const #32 = Asciz java/lang/Object;
const #33 = class #32; // java/lang/Object
const #34 = Method #33.#11; // java/lang/Object."<init>":()V
const #35 = NameAndType #3:#4;// MODULE$:LScalaHelloWorld2$;
const #36 = Field #9.#35; // ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
const #37 = Asciz Scala;
const #38 = Asciz InnerClasses;
const #39 = Asciz ScalaHelloWorld2;
const #40 = class #39; // ScalaHelloWorld2
const #41 = Asciz $anonfun$main$1;
const #42 = Asciz scala/ScalaObject;
const #43 = class #42; // scala/ScalaObject
{
public static final ScalaHelloWorld2$ MODULE$;
public static {};
Code:
Stack=1, Locals=0, Args_size=0
0: new #9; //class ScalaHelloWorld2$
3: invokespecial #12; //Method "<init>":()V
6: return
public void main(java.lang.String[]);
Code:
Stack=3, Locals=2, Args_size=2
0: getstatic #19; //Field eu/teraflux/uniman/transactions/TMLib$.MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
3: new #22; //class ScalaHelloWorld2$$anonfun$main$1
6: dup
7: invokespecial #23; //Method ScalaHelloWorld2$$anonfun$main$1."<init>":()V
10: invokevirtual #27; //Method eu/teraflux/uniman/transactions/TMLib$.atomic:(Lscala/Function1;)V
13: return
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 14 0 this LScalaHelloWorld2$;
0 14 1 args [Ljava/lang/String;
}
ScalaHelloWorld2$.class 2.9
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2$ extends java.lang.Object implements scala.ScalaObject
SourceFile: "ScalaHelloWorld2.scala"
Scala: length = 0x
InnerClass:
public final #22; //class ScalaHelloWorld2$$anonfun$main$1
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz MODULE$;
const #4 = Asciz LScalaHelloWorld2$;;
const #5 = Asciz <clinit>;
const #6 = Asciz ()V;
const #7 = Asciz Code;
const #8 = Asciz ScalaHelloWorld2$;
const #9 = class #8; // ScalaHelloWorld2$
const #10 = Asciz <init>;
const #11 = NameAndType #10:#6;// "<init>":()V
const #12 = Method #9.#11; // ScalaHelloWorld2$."<init>":()V
const #13 = Asciz main;
const #14 = Asciz ([Ljava/lang/String;)V;
const #15 = Asciz eu/teraflux/uniman/transactions/TMLib$;
const #16 = class #15; // eu/teraflux/uniman/transactions/TMLib$
const #17 = Asciz Leu/teraflux/uniman/transactions/TMLib$;;
const #18 = NameAndType #3:#17;// MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
const #19 = Field #16.#18; // eu/teraflux/uniman/transactions/TMLib$.MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
const #20 = Asciz LineNumberTable;
const #21 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #22 = class #21; // ScalaHelloWorld2$$anonfun$main$1
const #23 = Method #22.#11; // ScalaHelloWorld2$$anonfun$main$1."<init>":()V
const #24 = Asciz atomic;
const #25 = Asciz (Lscala/Function1;)V;
const #26 = NameAndType #24:#25;// atomic:(Lscala/Function1;)V
const #27 = Method #16.#26; // eu/teraflux/uniman/transactions/TMLib$.atomic:(Lscala/Function1;)V
const #28 = Asciz this;
const #29 = Asciz args;
const #30 = Asciz [Ljava/lang/String;;
const #31 = Asciz LocalVariableTable;
const #32 = Asciz java/lang/Object;
const #33 = class #32; // java/lang/Object
const #34 = Method #33.#11; // java/lang/Object."<init>":()V
const #35 = NameAndType #3:#4;// MODULE$:LScalaHelloWorld2$;
const #36 = Field #9.#35; // ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
const #37 = Asciz Scala;
const #38 = Asciz InnerClasses;
const #39 = Asciz scala/ScalaObject;
const #40 = class #39; // scala/ScalaObject
{
public static final ScalaHelloWorld2$ MODULE$;
public static {};
Code:
Stack=1, Locals=0, Args_size=0
0: new #9; //class ScalaHelloWorld2$
3: invokespecial #12; //Method "<init>":()V
6: return
public void main(java.lang.String[]);
Code:
Stack=3, Locals=2, Args_size=2
0: getstatic #19; //Field eu/teraflux/uniman/transactions/TMLib$.MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
3: new #22; //class ScalaHelloWorld2$$anonfun$main$1
6: dup
7: invokespecial #23; //Method ScalaHelloWorld2$$anonfun$main$1."<init>":()V
10: invokevirtual #27; //Method eu/teraflux/uniman/transactions/TMLib$.atomic:(Lscala/Function1;)V
13: return
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 14 0 this LScalaHelloWorld2$;
0 14 1 args [Ljava/lang/String;
}
ScalaHelloWorld2$$anonfun$main$1.class 2.8
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2$$anonfun$main$1 extends scala.runtime.AbstractFunction1 implements java.io.Serializable
SourceFile: "ScalaHelloWorld2.scala"
Scala: length = 0x
InnerClass:
public final #51= #9 of #50; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz <clinit>;
const #4 = Asciz ()V;
const #5 = Asciz Code;
const #6 = Asciz serialVersionUID;
const #7 = Asciz J;
const #8 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #9 = class #8; // ScalaHelloWorld2$$anonfun$main$1
const #10 = NameAndType #6:#7;// serialVersionUID:J
const #11 = Field #9.#10; // ScalaHelloWorld2$$anonfun$main$1.serialVersionUID:J
const #12 = Asciz apply;
const #13 = Asciz (Lscala/runtime/BoxedUnit;)V;
const #14 = Asciz scala/Predef$;
const #15 = class #14; // scala/Predef$
const #16 = Asciz MODULE$;
const #17 = Asciz Lscala/Predef$;;
const #18 = NameAndType #16:#17;// MODULE$:Lscala/Predef$;
const #19 = Field #15.#18; // scala/Predef$.MODULE$:Lscala/Predef$;
const #20 = Asciz LineNumberTable;
const #21 = Asciz Hello World from Scala;
const #22 = String #21; // Hello World from Scala
const #23 = Asciz println;
const #24 = Asciz (Ljava/lang/Object;)V;
const #25 = NameAndType #23:#24;// println:(Ljava/lang/Object;)V
const #26 = Method #15.#25; // scala/Predef$.println:(Ljava/lang/Object;)V
const #27 = Asciz this;
const #28 = Asciz LScalaHelloWorld2$$anonfun$main$1;;
const #29 = Asciz Unit;
const #30 = Asciz Lscala/runtime/BoxedUnit;;
const #31 = Asciz LocalVariableTable;
const #32 = Asciz (Ljava/lang/Object;)Ljava/lang/Object;;
const #33 = Asciz scala/runtime/BoxedUnit;
const #34 = class #33; // scala/runtime/BoxedUnit
const #35 = NameAndType #12:#13;// apply:(Lscala/runtime/BoxedUnit;)V
const #36 = Method #9.#35; // ScalaHelloWorld2$$anonfun$main$1.apply:(Lscala/runtime/BoxedUnit;)V
const #37 = Asciz UNIT;
const #38 = NameAndType #37:#30;// UNIT:Lscala/runtime/BoxedUnit;
const #39 = Field #34.#38; // scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
const #40 = Asciz v1;
const #41 = Asciz Ljava/lang/Object;;
const #42 = Asciz <init>;
const #43 = Asciz scala/runtime/AbstractFunction1;
const #44 = class #43; // scala/runtime/AbstractFunction1
const #45 = NameAndType #42:#4;// "<init>":()V
const #46 = Method #44.#45; // scala/runtime/AbstractFunction1."<init>":()V
const #47 = Asciz Scala;
const #48 = Asciz InnerClasses;
const #49 = Asciz ScalaHelloWorld2;
const #50 = class #49; // ScalaHelloWorld2
const #51 = Asciz $anonfun$main$1;
const #52 = Asciz java/io/Serializable;
const #53 = class #52; // java/io/Serializable
{
public static final long serialVersionUID;
public static {};
Code:
Stack=2, Locals=0, Args_size=0
0: lconst_0
1: putstatic #11; //Field serialVersionUID:J
4: return
public final void apply(scala.runtime.BoxedUnit);
Code:
Stack=2, Locals=2, Args_size=2
0: getstatic #19; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: ldc #22; //String Hello World from Scala
5: invokevirtual #26; //Method scala/Predef$.println:(Ljava/lang/Object;)V
8: return
LineNumberTable:
line 5: 0
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this LScalaHelloWorld2$$anonfun$main$1;
0 9 1 Unit Lscala/runtime/BoxedUnit;
public final java.lang.Object apply(java.lang.Object);
Code:
Stack=2, Locals=2, Args_size=2
0: aload_0
1: aload_1
2: checkcast #34; //class scala/runtime/BoxedUnit
5: invokevirtual #36; //Method apply:(Lscala/runtime/BoxedUnit;)V
8: getstatic #39; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
11: areturn
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 12 0 this LScalaHelloWorld2$$anonfun$main$1;
0 12 1 v1 Ljava/lang/Object;
public ScalaHelloWorld2$$anonfun$main$1();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #46; //Method scala/runtime/AbstractFunction1."<init>":()V
4: return
LineNumberTable:
line 4: 0
}
ScalaHelloWorld2$$anonfun$main$1.class 2.9
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2$$anonfun$main$1 extends scala.runtime.AbstractFunction1 implements scala.Serializable
SourceFile: "ScalaHelloWorld2.scala"
Scala: length = 0x
EnclosingMethod: length = 0x4
00 32 00 35
InnerClass:
public final #9; //class ScalaHelloWorld2$$anonfun$main$1
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz <clinit>;
const #4 = Asciz ()V;
const #5 = Asciz Code;
const #6 = Asciz serialVersionUID;
const #7 = Asciz J;
const #8 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #9 = class #8; // ScalaHelloWorld2$$anonfun$main$1
const #10 = NameAndType #6:#7;// serialVersionUID:J
const #11 = Field #9.#10; // ScalaHelloWorld2$$anonfun$main$1.serialVersionUID:J
const #12 = Asciz apply;
const #13 = Asciz (Lscala/runtime/BoxedUnit;)V;
const #14 = Asciz scala/Predef$;
const #15 = class #14; // scala/Predef$
const #16 = Asciz MODULE$;
const #17 = Asciz Lscala/Predef$;;
const #18 = NameAndType #16:#17;// MODULE$:Lscala/Predef$;
const #19 = Field #15.#18; // scala/Predef$.MODULE$:Lscala/Predef$;
const #20 = Asciz LineNumberTable;
const #21 = Asciz Hello World from Scala;
const #22 = String #21; // Hello World from Scala
const #23 = Asciz println;
const #24 = Asciz (Ljava/lang/Object;)V;
const #25 = NameAndType #23:#24;// println:(Ljava/lang/Object;)V
const #26 = Method #15.#25; // scala/Predef$.println:(Ljava/lang/Object;)V
const #27 = Asciz this;
const #28 = Asciz LScalaHelloWorld2$$anonfun$main$1;;
const #29 = Asciz Unit;
const #30 = Asciz Lscala/runtime/BoxedUnit;;
const #31 = Asciz LocalVariableTable;
const #32 = Asciz (Ljava/lang/Object;)Ljava/lang/Object;;
const #33 = Asciz scala/runtime/BoxedUnit;
const #34 = class #33; // scala/runtime/BoxedUnit
const #35 = NameAndType #12:#13;// apply:(Lscala/runtime/BoxedUnit;)V
const #36 = Method #9.#35; // ScalaHelloWorld2$$anonfun$main$1.apply:(Lscala/runtime/BoxedUnit;)V
const #37 = Asciz UNIT;
const #38 = NameAndType #37:#30;// UNIT:Lscala/runtime/BoxedUnit;
const #39 = Field #34.#38; // scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
const #40 = Asciz v1;
const #41 = Asciz Ljava/lang/Object;;
const #42 = Asciz <init>;
const #43 = Asciz scala/runtime/AbstractFunction1;
const #44 = class #43; // scala/runtime/AbstractFunction1
const #45 = NameAndType #42:#4;// "<init>":()V
const #46 = Method #44.#45; // scala/runtime/AbstractFunction1."<init>":()V
const #47 = Asciz Scala;
const #48 = Asciz EnclosingMethod;
const #49 = Asciz ScalaHelloWorld2$;
const #50 = class #49; // ScalaHelloWorld2$
const #51 = Asciz main;
const #52 = Asciz ([Ljava/lang/String;)V;
const #53 = NameAndType #51:#52;// main:([Ljava/lang/String;)V
const #54 = Asciz InnerClasses;
const #55 = Asciz scala/Serializable;
const #56 = class #55; // scala/Serializable
{
public static final long serialVersionUID;
public static {};
Code:
Stack=4, Locals=0, Args_size=0
0: lconst_0
1: lconst_0
2: putstatic #11; //Field serialVersionUID:J
5: return
public final void apply(scala.runtime.BoxedUnit);
Code:
Stack=2, Locals=2, Args_size=2
0: getstatic #19; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: ldc #22; //String Hello World from Scala
5: invokevirtual #26; //Method scala/Predef$.println:(Ljava/lang/Object;)V
8: return
LineNumberTable:
line 5: 0
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this LScalaHelloWorld2$$anonfun$main$1;
0 9 1 Unit Lscala/runtime/BoxedUnit;
public final java.lang.Object apply(java.lang.Object);
Code:
Stack=2, Locals=2, Args_size=2
0: aload_0
1: aload_1
2: checkcast #34; //class scala/runtime/BoxedUnit
5: invokevirtual #36; //Method apply:(Lscala/runtime/BoxedUnit;)V
8: getstatic #39; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
11: areturn
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 12 0 this LScalaHelloWorld2$$anonfun$main$1;
0 12 1 v1 Ljava/lang/Object;
public ScalaHelloWorld2$$anonfun$main$1();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #46; //Method scala/runtime/AbstractFunction1."<init>":()V
4: return
LineNumberTable:
line 4: 0
}
On 11/07/11 15:27, Daniel Goodman wrote:
So I am still trying to narrow down the cause of this issue. Experimenting with a specific case showed that running 2.8 or 2.9 code on the 2.9 version of scala throws a method not found exception when the code tried to access a new method added by the byte code rewrite. Running these versions against the 2.8 version of scala, the files compiled with the 2.8 version of scalac worked, but the ones compiled with the 2.9 version failed with a java.lang.NoClassDefFound Error. This appeared to be being thrown by the class loader. As this gave me a small piece of code to examine, where one version worked and one did not I decided to start examining the code here.
Examining the byte code shows that byte code instructions that make up the different methods are identical. This would appear to mean that it is the way the runtime environment uses the remaining meta-data in the class that is making the difference. To try and isolate this first I tried to strip back the command used in scala such that the code was running directly on the JVM rather than in an augmented runtime. However the closest I could get is as follows:
2.8
java -javaagent:muts_2.8.jar -cp /usr/scala-2.8.1.final/lib/scala-compiler.jar:/usr/scala-2.8.1.final/lib/scala-library.jar -Dscala.home=/usr/scala-2.8.1.final scala.tools.nsc.MainGenericRunner -cp .:./muts_2.8.jar ScalaHelloWorld
2.9
java -javaagent:muts_2.8.jar -cp muts_2.8.jar:. -Xbootclasspath/a:/usr/share/scala/lib/scala-library.jar ScalaHelloWorld
This would appear to show that Scala class files require an augmented runtime to execute. So the first questions are: Can I run scala code without either using an additional program or changing classes in the JVM? Secondly, in each of these cases what is the augmented functionality?
Next I looked at the fields in more detail: the code I compiled was:
import eu.teraflux.uniman.transactions.TMLib._
object ScalaHelloWorld2 {
def main(args:Array[String]) {
atomic{ Unit =>
println("Hello World from Scala")
}
}
}
which results in the three bytecode files being produced: ScalaHelloWorld2.class; ScalaHelloWorld2$.class and ScalaHelloWorld2$$anonfun$main$1.class. According to JavaP the differences between these classes are as follows.
ScalaHelloWorld2.class
2.8 contains
InnerClass:
public final #24= #21 of #23; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
which becomes
InnerClass:
public final #21; //class ScalaHelloWorld2$$anonfun$main$1
in 2.9.
The scala signatures are also different, 2.8 is
const #17 = Asciz 5:Q!\t\tcU2bYDU\r7p/>H\r\tqP3naRLhh9Q\"!A!A\t%cU2bYDU\r7p/>HQ!!5\tAB!A.8hy6bmL!!\r='.Z2u!\tb#D)!B:dC2BA-6-7b\nTWm;\te9A\rqJg.;?))\"\tiB7bS:$\"AHMyB)f.;\t\tZA\txm\t'2BA\t%O]1z!\t9#FQ%F!J,G-4\n-b#AB*ue&twM*);
and 2.9 is
const #17 = Asciz 5:Q!\t\tcU2bYDU\r7p/>H\r\tqP3naRLhh9Q\"!RA!M\r\1IK2dwnV8sY4cA%A1E)QBDYtwMCQM^1\nEa!AB(cUG-5\tACC8-7b\t9BCATGdm2kK$\"B\r\tQAj]&$hFar\"i-8y\tCA\n \tCCV]&$\"B1sON2a'\t)CCABeJ(U91KSQ\ta:fI4BA-FO]5oO*;
finally 2.8 also contains the following extra constant
const #24 = Asciz java/lang/Object;
ScalaHelloWorld2$.class
2.8 contains
InnerClass:
public final #41= #22 of #40; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
which becomes
InnerClass:
public final #22; //class ScalaHelloWorld2$$anonfun$main$1
in 2.9. 2.8 also contains the following extra constants
const #39 = Asciz ScalaHelloWorld2;
const #40 = class #39; // ScalaHelloWorld2
const #41 = Asciz $anonfun$main$1;
ScalaHelloWorld2$$anonfun$main$1.class
Finally
the 2.8 headers change from
InnerClass:
public final #51= #9 of #50; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
to
EnclosingMethod: length = 0x4
00 32 00 35
InnerClass:
public final #9; //class ScalaHelloWorld2$$anonfun$main$1
and the interface implemented changes from java.io.Serializable to scala.Serializable
I have included the full text of each of the methods at the end of the email incase I have missed out an important detail here. My last question is as my rewrite does not change any of these values, but augments the constant pool with additional values to support the additional instrumented methods, is anyone aware of what in these changes is causing the re-writen code to fail for the 2.9 code, but not for the 2.8 code?
Many thanks in advance
Daniel
ScalaHelloWorld2.class 2.8
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2 extends java.lang.Object
SourceFile: "ScalaHelloWorld2.scala"
ScalaSig: length = 0x3
05 00 00
RuntimeVisibleAnnotations: length = 0xB
00 01 00 0F 00 01 00 10 73 00 11
InnerClass:
public final #24= #21 of #23; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz main;
const #4 = Asciz ([Ljava/lang/String;)V;
const #5 = Asciz Code;
const #6 = Asciz ScalaHelloWorld2$;
const #7 = class #6; // ScalaHelloWorld2$
const #8 = Asciz MODULE$;
const #9 = Asciz LScalaHelloWorld2$;;
const #10 = NameAndType #8:#9;// MODULE$:LScalaHelloWorld2$;
const #11 = Field #7.#10; // ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
const #12 = NameAndType #3:#4;// main:([Ljava/lang/String;)V
const #13 = Method #7.#12; // ScalaHelloWorld2$.main:([Ljava/lang/String;)V
const #14 = Asciz ScalaSig;
const #15 = Asciz Lscala/reflect/ScalaSignature;;
const #16 = Asciz bytes;
const #17 = Asciz 5:Q!\t\tcU2bYDU\r7p/>H\r\tqP3naRLhh9Q\"!A!A\t%cU2bYDU\r7p/>HQ!!5\tAB!A.8hy6bmL!!\r='.Z2u!\tb#D)!B:dC2BA-6-7b\nTWm;\te9A\rqJg.;?))\"\tiB7bS:$\"AHMyB)f.;\t\tZA\txm\t'2BA\t%O]1z!\t9#FQ%F!J,G-4\n-b#AB*ue&twM*);
const #18 = Asciz RuntimeVisibleAnnotations;
const #19 = Asciz InnerClasses;
const #20 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #21 = class #20; // ScalaHelloWorld2$$anonfun$main$1
const #22 = Asciz ScalaHelloWorld2;
const #23 = class #22; // ScalaHelloWorld2
const #24 = Asciz $anonfun$main$1;
const #25 = Asciz java/lang/Object;
const #26 = class #25; // java/lang/Object
{
public static final void main(java.lang.String[]);
Code:
Stack=2, Locals=1, Args_size=1
0: getstatic #11; //Field ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
3: aload_0
4: invokevirtual #13; //Method ScalaHelloWorld2$.main:([Ljava/lang/String;)V
7: return
}
ScalaHelloWorld2.class 2.9
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2 extends java.lang.Object
SourceFile: "ScalaHelloWorld2.scala"
ScalaSig: length = 0x3
05 00 00
RuntimeVisibleAnnotations: length = 0xB
00 01 00 0F 00 01 00 10 73 00 11
InnerClass:
public final #21; //class ScalaHelloWorld2$$anonfun$main$1
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz main;
const #4 = Asciz ([Ljava/lang/String;)V;
const #5 = Asciz Code;
const #6 = Asciz ScalaHelloWorld2$;
const #7 = class #6; // ScalaHelloWorld2$
const #8 = Asciz MODULE$;
const #9 = Asciz LScalaHelloWorld2$;;
const #10 = NameAndType #8:#9;// MODULE$:LScalaHelloWorld2$;
const #11 = Field #7.#10; // ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
const #12 = NameAndType #3:#4;// main:([Ljava/lang/String;)V
const #13 = Method #7.#12; // ScalaHelloWorld2$.main:([Ljava/lang/String;)V
const #14 = Asciz ScalaSig;
const #15 = Asciz Lscala/reflect/ScalaSignature;;
const #16 = Asciz bytes;
const #17 = Asciz 5:Q!\t\tcU2bYDU\r7p/>H\r\tqP3naRLhh9Q\"!RA!M\r\1IK2dwnV8sY4cA%A1E)QBDYtwMCQM^1\nEa!AB(cUG-5\tACC8-7b\t9BCATGdm2kK$\"B\r\tQAj]&$hFar\"i-8y\tCA\n \tCCV]&$\"B1sON2a'\t)CCABeJ(U91KSQ\ta:fI4BA-FO]5oO*;
const #18 = Asciz RuntimeVisibleAnnotations;
const #19 = Asciz InnerClasses;
const #20 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #21 = class #20; // ScalaHelloWorld2$$anonfun$main$1
const #22 = Asciz ScalaHelloWorld2;
const #23 = class #22; // ScalaHelloWorld2
const #24 = Asciz java/lang/Object;
const #25 = class #24; // java/lang/Object
{
public static final void main(java.lang.String[]);
Code:
Stack=2, Locals=1, Args_size=1
0: getstatic #11; //Field ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
3: aload_0
4: invokevirtual #13; //Method ScalaHelloWorld2$.main:([Ljava/lang/String;)V
7: return
}
ScalaHelloWorld2$.class 2.8
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2$ extends java.lang.Object implements scala.ScalaObject
SourceFile: "ScalaHelloWorld2.scala"
Scala: length = 0x
InnerClass:
public final #41= #22 of #40; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz MODULE$;
const #4 = Asciz LScalaHelloWorld2$;;
const #5 = Asciz <clinit>;
const #6 = Asciz ()V;
const #7 = Asciz Code;
const #8 = Asciz ScalaHelloWorld2$;
const #9 = class #8; // ScalaHelloWorld2$
const #10 = Asciz <init>;
const #11 = NameAndType #10:#6;// "<init>":()V
const #12 = Method #9.#11; // ScalaHelloWorld2$."<init>":()V
const #13 = Asciz main;
const #14 = Asciz ([Ljava/lang/String;)V;
const #15 = Asciz eu/teraflux/uniman/transactions/TMLib$;
const #16 = class #15; // eu/teraflux/uniman/transactions/TMLib$
const #17 = Asciz Leu/teraflux/uniman/transactions/TMLib$;;
const #18 = NameAndType #3:#17;// MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
const #19 = Field #16.#18; // eu/teraflux/uniman/transactions/TMLib$.MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
const #20 = Asciz LineNumberTable;
const #21 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #22 = class #21; // ScalaHelloWorld2$$anonfun$main$1
const #23 = Method #22.#11; // ScalaHelloWorld2$$anonfun$main$1."<init>":()V
const #24 = Asciz atomic;
const #25 = Asciz (Lscala/Function1;)V;
const #26 = NameAndType #24:#25;// atomic:(Lscala/Function1;)V
const #27 = Method #16.#26; // eu/teraflux/uniman/transactions/TMLib$.atomic:(Lscala/Function1;)V
const #28 = Asciz this;
const #29 = Asciz args;
const #30 = Asciz [Ljava/lang/String;;
const #31 = Asciz LocalVariableTable;
const #32 = Asciz java/lang/Object;
const #33 = class #32; // java/lang/Object
const #34 = Method #33.#11; // java/lang/Object."<init>":()V
const #35 = NameAndType #3:#4;// MODULE$:LScalaHelloWorld2$;
const #36 = Field #9.#35; // ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
const #37 = Asciz Scala;
const #38 = Asciz InnerClasses;
const #39 = Asciz ScalaHelloWorld2;
const #40 = class #39; // ScalaHelloWorld2
const #41 = Asciz $anonfun$main$1;
const #42 = Asciz scala/ScalaObject;
const #43 = class #42; // scala/ScalaObject
{
public static final ScalaHelloWorld2$ MODULE$;
public static {};
Code:
Stack=1, Locals=0, Args_size=0
0: new #9; //class ScalaHelloWorld2$
3: invokespecial #12; //Method "<init>":()V
6: return
public void main(java.lang.String[]);
Code:
Stack=3, Locals=2, Args_size=2
0: getstatic #19; //Field eu/teraflux/uniman/transactions/TMLib$.MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
3: new #22; //class ScalaHelloWorld2$$anonfun$main$1
6: dup
7: invokespecial #23; //Method ScalaHelloWorld2$$anonfun$main$1."<init>":()V
10: invokevirtual #27; //Method eu/teraflux/uniman/transactions/TMLib$.atomic:(Lscala/Function1;)V
13: return
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 14 0 this LScalaHelloWorld2$;
0 14 1 args [Ljava/lang/String;
}
ScalaHelloWorld2$.class 2.9
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2$ extends java.lang.Object implements scala.ScalaObject
SourceFile: "ScalaHelloWorld2.scala"
Scala: length = 0x
InnerClass:
public final #22; //class ScalaHelloWorld2$$anonfun$main$1
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz MODULE$;
const #4 = Asciz LScalaHelloWorld2$;;
const #5 = Asciz <clinit>;
const #6 = Asciz ()V;
const #7 = Asciz Code;
const #8 = Asciz ScalaHelloWorld2$;
const #9 = class #8; // ScalaHelloWorld2$
const #10 = Asciz <init>;
const #11 = NameAndType #10:#6;// "<init>":()V
const #12 = Method #9.#11; // ScalaHelloWorld2$."<init>":()V
const #13 = Asciz main;
const #14 = Asciz ([Ljava/lang/String;)V;
const #15 = Asciz eu/teraflux/uniman/transactions/TMLib$;
const #16 = class #15; // eu/teraflux/uniman/transactions/TMLib$
const #17 = Asciz Leu/teraflux/uniman/transactions/TMLib$;;
const #18 = NameAndType #3:#17;// MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
const #19 = Field #16.#18; // eu/teraflux/uniman/transactions/TMLib$.MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
const #20 = Asciz LineNumberTable;
const #21 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #22 = class #21; // ScalaHelloWorld2$$anonfun$main$1
const #23 = Method #22.#11; // ScalaHelloWorld2$$anonfun$main$1."<init>":()V
const #24 = Asciz atomic;
const #25 = Asciz (Lscala/Function1;)V;
const #26 = NameAndType #24:#25;// atomic:(Lscala/Function1;)V
const #27 = Method #16.#26; // eu/teraflux/uniman/transactions/TMLib$.atomic:(Lscala/Function1;)V
const #28 = Asciz this;
const #29 = Asciz args;
const #30 = Asciz [Ljava/lang/String;;
const #31 = Asciz LocalVariableTable;
const #32 = Asciz java/lang/Object;
const #33 = class #32; // java/lang/Object
const #34 = Method #33.#11; // java/lang/Object."<init>":()V
const #35 = NameAndType #3:#4;// MODULE$:LScalaHelloWorld2$;
const #36 = Field #9.#35; // ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
const #37 = Asciz Scala;
const #38 = Asciz InnerClasses;
const #39 = Asciz scala/ScalaObject;
const #40 = class #39; // scala/ScalaObject
{
public static final ScalaHelloWorld2$ MODULE$;
public static {};
Code:
Stack=1, Locals=0, Args_size=0
0: new #9; //class ScalaHelloWorld2$
3: invokespecial #12; //Method "<init>":()V
6: return
public void main(java.lang.String[]);
Code:
Stack=3, Locals=2, Args_size=2
0: getstatic #19; //Field eu/teraflux/uniman/transactions/TMLib$.MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
3: new #22; //class ScalaHelloWorld2$$anonfun$main$1
6: dup
7: invokespecial #23; //Method ScalaHelloWorld2$$anonfun$main$1."<init>":()V
10: invokevirtual #27; //Method eu/teraflux/uniman/transactions/TMLib$.atomic:(Lscala/Function1;)V
13: return
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 14 0 this LScalaHelloWorld2$;
0 14 1 args [Ljava/lang/String;
}
ScalaHelloWorld2$$anonfun$main$1.class 2.8
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2$$anonfun$main$1 extends scala.runtime.AbstractFunction1 implements java.io.Serializable
SourceFile: "ScalaHelloWorld2.scala"
Scala: length = 0x
InnerClass:
public final #51= #9 of #50; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz <clinit>;
const #4 = Asciz ()V;
const #5 = Asciz Code;
const #6 = Asciz serialVersionUID;
const #7 = Asciz J;
const #8 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #9 = class #8; // ScalaHelloWorld2$$anonfun$main$1
const #10 = NameAndType #6:#7;// serialVersionUID:J
const #11 = Field #9.#10; // ScalaHelloWorld2$$anonfun$main$1.serialVersionUID:J
const #12 = Asciz apply;
const #13 = Asciz (Lscala/runtime/BoxedUnit;)V;
const #14 = Asciz scala/Predef$;
const #15 = class #14; // scala/Predef$
const #16 = Asciz MODULE$;
const #17 = Asciz Lscala/Predef$;;
const #18 = NameAndType #16:#17;// MODULE$:Lscala/Predef$;
const #19 = Field #15.#18; // scala/Predef$.MODULE$:Lscala/Predef$;
const #20 = Asciz LineNumberTable;
const #21 = Asciz Hello World from Scala;
const #22 = String #21; // Hello World from Scala
const #23 = Asciz println;
const #24 = Asciz (Ljava/lang/Object;)V;
const #25 = NameAndType #23:#24;// println:(Ljava/lang/Object;)V
const #26 = Method #15.#25; // scala/Predef$.println:(Ljava/lang/Object;)V
const #27 = Asciz this;
const #28 = Asciz LScalaHelloWorld2$$anonfun$main$1;;
const #29 = Asciz Unit;
const #30 = Asciz Lscala/runtime/BoxedUnit;;
const #31 = Asciz LocalVariableTable;
const #32 = Asciz (Ljava/lang/Object;)Ljava/lang/Object;;
const #33 = Asciz scala/runtime/BoxedUnit;
const #34 = class #33; // scala/runtime/BoxedUnit
const #35 = NameAndType #12:#13;// apply:(Lscala/runtime/BoxedUnit;)V
const #36 = Method #9.#35; // ScalaHelloWorld2$$anonfun$main$1.apply:(Lscala/runtime/BoxedUnit;)V
const #37 = Asciz UNIT;
const #38 = NameAndType #37:#30;// UNIT:Lscala/runtime/BoxedUnit;
const #39 = Field #34.#38; // scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
const #40 = Asciz v1;
const #41 = Asciz Ljava/lang/Object;;
const #42 = Asciz <init>;
const #43 = Asciz scala/runtime/AbstractFunction1;
const #44 = class #43; // scala/runtime/AbstractFunction1
const #45 = NameAndType #42:#4;// "<init>":()V
const #46 = Method #44.#45; // scala/runtime/AbstractFunction1."<init>":()V
const #47 = Asciz Scala;
const #48 = Asciz InnerClasses;
const #49 = Asciz ScalaHelloWorld2;
const #50 = class #49; // ScalaHelloWorld2
const #51 = Asciz $anonfun$main$1;
const #52 = Asciz java/io/Serializable;
const #53 = class #52; // java/io/Serializable
{
public static final long serialVersionUID;
public static {};
Code:
Stack=2, Locals=0, Args_size=0
0: lconst_0
1: putstatic #11; //Field serialVersionUID:J
4: return
public final void apply(scala.runtime.BoxedUnit);
Code:
Stack=2, Locals=2, Args_size=2
0: getstatic #19; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: ldc #22; //String Hello World from Scala
5: invokevirtual #26; //Method scala/Predef$.println:(Ljava/lang/Object;)V
8: return
LineNumberTable:
line 5: 0
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this LScalaHelloWorld2$$anonfun$main$1;
0 9 1 Unit Lscala/runtime/BoxedUnit;
public final java.lang.Object apply(java.lang.Object);
Code:
Stack=2, Locals=2, Args_size=2
0: aload_0
1: aload_1
2: checkcast #34; //class scala/runtime/BoxedUnit
5: invokevirtual #36; //Method apply:(Lscala/runtime/BoxedUnit;)V
8: getstatic #39; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
11: areturn
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 12 0 this LScalaHelloWorld2$$anonfun$main$1;
0 12 1 v1 Ljava/lang/Object;
public ScalaHelloWorld2$$anonfun$main$1();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #46; //Method scala/runtime/AbstractFunction1."<init>":()V
4: return
LineNumberTable:
line 4: 0
}
ScalaHelloWorld2$$anonfun$main$1.class 2.9
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2$$anonfun$main$1 extends scala.runtime.AbstractFunction1 implements scala.Serializable
SourceFile: "ScalaHelloWorld2.scala"
Scala: length = 0x
EnclosingMethod: length = 0x4
00 32 00 35
InnerClass:
public final #9; //class ScalaHelloWorld2$$anonfun$main$1
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz <clinit>;
const #4 = Asciz ()V;
const #5 = Asciz Code;
const #6 = Asciz serialVersionUID;
const #7 = Asciz J;
const #8 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #9 = class #8; // ScalaHelloWorld2$$anonfun$main$1
const #10 = NameAndType #6:#7;// serialVersionUID:J
const #11 = Field #9.#10; // ScalaHelloWorld2$$anonfun$main$1.serialVersionUID:J
const #12 = Asciz apply;
const #13 = Asciz (Lscala/runtime/BoxedUnit;)V;
const #14 = Asciz scala/Predef$;
const #15 = class #14; // scala/Predef$
const #16 = Asciz MODULE$;
const #17 = Asciz Lscala/Predef$;;
const #18 = NameAndType #16:#17;// MODULE$:Lscala/Predef$;
const #19 = Field #15.#18; // scala/Predef$.MODULE$:Lscala/Predef$;
const #20 = Asciz LineNumberTable;
const #21 = Asciz Hello World from Scala;
const #22 = String #21; // Hello World from Scala
const #23 = Asciz println;
const #24 = Asciz (Ljava/lang/Object;)V;
const #25 = NameAndType #23:#24;// println:(Ljava/lang/Object;)V
const #26 = Method #15.#25; // scala/Predef$.println:(Ljava/lang/Object;)V
const #27 = Asciz this;
const #28 = Asciz LScalaHelloWorld2$$anonfun$main$1;;
const #29 = Asciz Unit;
const #30 = Asciz Lscala/runtime/BoxedUnit;;
const #31 = Asciz LocalVariableTable;
const #32 = Asciz (Ljava/lang/Object;)Ljava/lang/Object;;
const #33 = Asciz scala/runtime/BoxedUnit;
const #34 = class #33; // scala/runtime/BoxedUnit
const #35 = NameAndType #12:#13;// apply:(Lscala/runtime/BoxedUnit;)V
const #36 = Method #9.#35; // ScalaHelloWorld2$$anonfun$main$1.apply:(Lscala/runtime/BoxedUnit;)V
const #37 = Asciz UNIT;
const #38 = NameAndType #37:#30;// UNIT:Lscala/runtime/BoxedUnit;
const #39 = Field #34.#38; // scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
const #40 = Asciz v1;
const #41 = Asciz Ljava/lang/Object;;
const #42 = Asciz <init>;
const #43 = Asciz scala/runtime/AbstractFunction1;
const #44 = class #43; // scala/runtime/AbstractFunction1
const #45 = NameAndType #42:#4;// "<init>":()V
const #46 = Method #44.#45; // scala/runtime/AbstractFunction1."<init>":()V
const #47 = Asciz Scala;
const #48 = Asciz EnclosingMethod;
const #49 = Asciz ScalaHelloWorld2$;
const #50 = class #49; // ScalaHelloWorld2$
const #51 = Asciz main;
const #52 = Asciz ([Ljava/lang/String;)V;
const #53 = NameAndType #51:#52;// main:([Ljava/lang/String;)V
const #54 = Asciz InnerClasses;
const #55 = Asciz scala/Serializable;
const #56 = class #55; // scala/Serializable
{
public static final long serialVersionUID;
public static {};
Code:
Stack=4, Locals=0, Args_size=0
0: lconst_0
1: lconst_0
2: putstatic #11; //Field serialVersionUID:J
5: return
public final void apply(scala.runtime.BoxedUnit);
Code:
Stack=2, Locals=2, Args_size=2
0: getstatic #19; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: ldc #22; //String Hello World from Scala
5: invokevirtual #26; //Method scala/Predef$.println:(Ljava/lang/Object;)V
8: return
LineNumberTable:
line 5: 0
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this LScalaHelloWorld2$$anonfun$main$1;
0 9 1 Unit Lscala/runtime/BoxedUnit;
public final java.lang.Object apply(java.lang.Object);
Code:
Stack=2, Locals=2, Args_size=2
0: aload_0
1: aload_1
2: checkcast #34; //class scala/runtime/BoxedUnit
5: invokevirtual #36; //Method apply:(Lscala/runtime/BoxedUnit;)V
8: getstatic #39; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
11: areturn
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 12 0 this LScalaHelloWorld2$$anonfun$main$1;
0 12 1 v1 Ljava/lang/Object;
public ScalaHelloWorld2$$anonfun$main$1();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #46; //Method scala/runtime/AbstractFunction1."<init>":()V
4: return
LineNumberTable:
line 4: 0
}
On 11/07/11 15:27, Daniel Goodman wrote:
4E1B086B [dot] 4080701 [at] cs [dot] man [dot] ac [dot] uk" type="cite"> Hi Martin,
Thanks for getting back to me. My code does not use the Java Signature attribute, so I am relatively sure that this is no the cause. However I will keep narrowing this down and try to come back to you in with more specific questions. In the mean time if anyone else has any thoughts I would love to hear from you.
All the best
Daniel
On 09/07/11 13:19, martin odersky wrote:dhP8VCkidF9kdpy0w [at] mail [dot] gmail [dot] com" type="cite">One change which might be relevant is that Java generic signatures have changed between 2.8 and 2.9. 2.8 generated sometimes incorrect signatures for Java generics. These have changed in 2.9. So if you code depends on the JavaSignature attribute it needs to be updated.
Cheers
-- Martin
On Sat, Jul 9, 2011 at 12:28 PM, Daniel Goodman <goodmand [at] cs [dot] man [dot] ac [dot] uk" rel="nofollow">goodmand@cs.man.ac.uk> wrote:
Hi,
I tried sending this to Scala users and got no takers, so given it is related to the internals of the system I thought I would give this list a try. I hope this is ok.
I have a problem with a change in the behaviour of Scala between version 2.9 and the earlier versions, and am hoping someone can save me some time by pointing me in the correct direction for solving it.
I'm building various Transactional Memory solutions for Scala. These are based on the Deuce STM approach of using Java Agents to perform a byte code rewrite at run time. This rewrite creates instrumented duplicates of the methods that appear in the classes. These duplicates can then be used to execute sections of code transactionally. This is done in conjunction with additionally created classes that hold information about the positions of fields within the original classes.
So far so good, and this all works fine with Scala 2.7 and 2.8, the problems arises with Scala 2.9. When trying to use this system under 2.9 the program fails with depending on which of my TM set-ups I'm using a field or a method not found exception. In both cases these are fields or methods that should have been added by the Java Agent. It would appear that the code that the JVM is seeing at this point has not been extended by the Java Agent. The addition of print statements confirms that the Java Agent is running for the classes required. The fact that the program is trying to access the fields that are only inserted by the Java Agent shows that at least some of the rewritten code is being executed. Examining the compiled Scala code shows no obvious changes for the files in question between 2.7 and 2.9. Running the Java Agent on the code outside of the runtime environment produces the correct rewritten code. All of these tests have been performed with the same JVM. Does anyone have any thoughts on what has changed between 2.8 and 2.9 that would cause this error? Is there some new verification of class signatures?
Many thanks in advance
Daniel
--
Martin Odersky
Prof., EPFL and Chairman, Typesafe
PSED, 1015 Lausanne, Switzerland
Tel. EPFL: +41 21 693 6863
Tel. Typesafe: +41 21 691 4967
Wed, 2011-07-13, 18:07
#4
Re: Change of behaviour between Scala2.[7-8] and 2.9 when using
Hi,
So on further investigation I realised that scala.Serializable is not actually part of the 2.8 libraries. Taking the source from the 2.9 library, compiling it with the 2.8 compiler and inserting it into the scala-library jar files overcomes the problem of running 2.9 code on the 2.8 scala command. This does still leave me with two questions about the 2.8 runtime.
1. Is Scala 2.9 code meant to not be compatible with the Scala 2.8 runtime?
2. Why didn't the 2.8 runtime try to load scala.Serializable when the byte-code was in its original form? This would seem to be an error.
For the 2.9 Runtime, I am still unsure why it is failing to find code I know the java agent is producing. Does the -Xbootclasspath/a argument change the class loader?
Daniel
On 13/07/11 16:48, Daniel Goodman wrote:
So on further investigation I realised that scala.Serializable is not actually part of the 2.8 libraries. Taking the source from the 2.9 library, compiling it with the 2.8 compiler and inserting it into the scala-library jar files overcomes the problem of running 2.9 code on the 2.8 scala command. This does still leave me with two questions about the 2.8 runtime.
1. Is Scala 2.9 code meant to not be compatible with the Scala 2.8 runtime?
2. Why didn't the 2.8 runtime try to load scala.Serializable when the byte-code was in its original form? This would seem to be an error.
For the 2.9 Runtime, I am still unsure why it is failing to find code I know the java agent is producing. Does the -Xbootclasspath/a argument change the class loader?
Daniel
On 13/07/11 16:48, Daniel Goodman wrote:
4E1DBE67 [dot] 6030903 [at] cs [dot] man [dot] ac [dot] uk" type="cite"> Hi,
So I am still trying to narrow down the cause of this issue. Experimenting with a specific case showed that running 2.8 or 2.9 code on the 2.9 version of scala throws a method not found exception when the code tried to access a new method added by the byte code rewrite. Running these versions against the 2.8 version of scala, the files compiled with the 2.8 version of scalac worked, but the ones compiled with the 2.9 version failed with a java.lang.NoClassDefFound Error. This appeared to be being thrown by the class loader. As this gave me a small piece of code to examine, where one version worked and one did not I decided to start examining the code here.
Examining the byte code shows that byte code instructions that make up the different methods are identical. This would appear to mean that it is the way the runtime environment uses the remaining meta-data in the class that is making the difference. To try and isolate this first I tried to strip back the command used in scala such that the code was running directly on the JVM rather than in an augmented runtime. However the closest I could get is as follows:
2.8
java -javaagent:muts_2.8.jar -cp /usr/scala-2.8.1.final/lib/scala-compiler.jar:/usr/scala-2.8.1.final/lib/scala-library.jar -Dscala.home=/usr/scala-2.8.1.final scala.tools.nsc.MainGenericRunner -cp .:./muts_2.8.jar ScalaHelloWorld
2.9
java -javaagent:muts_2.8.jar -cp muts_2.8.jar:. -Xbootclasspath/a:/usr/share/scala/lib/scala-library.jar ScalaHelloWorld
This would appear to show that Scala class files require an augmented runtime to execute. So the first questions are: Can I run scala code without either using an additional program or changing classes in the JVM? Secondly, in each of these cases what is the augmented functionality?
Next I looked at the fields in more detail: the code I compiled was:
import eu.teraflux.uniman.transactions.TMLib._
object ScalaHelloWorld2 {
def main(args:Array[String]) {
atomic{ Unit =>
println("Hello World from Scala")
}
}
}
which results in the three bytecode files being produced: ScalaHelloWorld2.class; ScalaHelloWorld2$.class and ScalaHelloWorld2$$anonfun$main$1.class. According to JavaP the differences between these classes are as follows.
ScalaHelloWorld2.class
2.8 contains
InnerClass:
public final #24= #21 of #23; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
which becomes
InnerClass:
public final #21; //class ScalaHelloWorld2$$anonfun$main$1
in 2.9.
The scala signatures are also different, 2.8 is
const #17 = Asciz 5:Q!\t\tcU2bYDU\r7p/>H\r\tqP3naRLhh9Q\"!A!A\t%cU2bYDU\r7p/>HQ!!5\tAB!A.8hy6bmL!!\r='.Z2u!\tb#D)!B:dC2BA-6-7b\nTWm;\te9A\rqJg.;?))\"\tiB7bS:$\"AHMyB)f.;\t\tZA\txm\t'2BA\t%O]1z!\t9#FQ%F!J,G-4\n-b#AB*ue&twM*);
and 2.9 is
const #17 = Asciz 5:Q!\t\tcU2bYDU\r7p/>H\r\tqP3naRLhh9Q\"!RA!M\r\1IK2dwnV8sY4cA%A1E)QBDYtwMCQM^1\nEa!AB(cUG-5\tACC8-7b\t9BCATGdm2kK$\"B\r\tQAj]&$hFar\"i-8y\tCA\n\tCCV]&$\"B1sON2a'\t)CCABeJ(U91KSQ\ta:fI4BA-FO]5oO*;
finally 2.8 also contains the following extra constant
const #24 = Asciz java/lang/Object;
ScalaHelloWorld2$.class
2.8 contains
InnerClass:
public final #41= #22 of #40; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
which becomes
InnerClass:
public final #22; //class ScalaHelloWorld2$$anonfun$main$1
in 2.9. 2.8 also contains the following extra constants
const #39 = Asciz ScalaHelloWorld2;
const #40 = class #39; // ScalaHelloWorld2
const #41 = Asciz $anonfun$main$1;
ScalaHelloWorld2$$anonfun$main$1.class
Finally
the 2.8 headers change from
InnerClass:
public final #51= #9 of #50; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
to
EnclosingMethod: length = 0x4
00 32 00 35
InnerClass:
public final #9; //class ScalaHelloWorld2$$anonfun$main$1
and the interface implemented changes from java.io.Serializable to scala.Serializable
I have included the full text of each of the methods at the end of the email incase I have missed out an important detail here. My last question is as my rewrite does not change any of these values, but augments the constant pool with additional values to support the additional instrumented methods, is anyone aware of what in these changes is causing the re-writen code to fail for the 2.9 code, but not for the 2.8 code?
Many thanks in advance
Daniel
ScalaHelloWorld2.class 2.8
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2 extends java.lang.Object
SourceFile: "ScalaHelloWorld2.scala"
ScalaSig: length = 0x3
05 00 00
RuntimeVisibleAnnotations: length = 0xB
00 01 00 0F 00 01 00 10 73 00 11
InnerClass:
public final #24= #21 of #23; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz main;
const #4 = Asciz ([Ljava/lang/String;)V;
const #5 = Asciz Code;
const #6 = Asciz ScalaHelloWorld2$;
const #7 = class #6; // ScalaHelloWorld2$
const #8 = Asciz MODULE$;
const #9 = Asciz LScalaHelloWorld2$;;
const #10 = NameAndType #8:#9;// MODULE$:LScalaHelloWorld2$;
const #11 = Field #7.#10; // ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
const #12 = NameAndType #3:#4;// main:([Ljava/lang/String;)V
const #13 = Method #7.#12; // ScalaHelloWorld2$.main:([Ljava/lang/String;)V
const #14 = Asciz ScalaSig;
const #15 = Asciz Lscala/reflect/ScalaSignature;;
const #16 = Asciz bytes;
const #17 = Asciz 5:Q!\t\tcU2bYDU\r7p/>H\r\tqP3naRLhh9Q\"!A!A\t%cU2bYDU\r7p/>HQ!!5\tAB!A.8hy6bmL!!\r='.Z2u!\tb#D)!B:dC2BA-6-7b\nTWm;\te9A\rqJg.;?))\"\tiB7bS:$\"AHMyB)f.;\t\tZA\txm\t'2BA\t%O]1z!\t9#FQ%F!J,G-4\n-b#AB*ue&twM*);
const #18 = Asciz RuntimeVisibleAnnotations;
const #19 = Asciz InnerClasses;
const #20 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #21 = class #20; // ScalaHelloWorld2$$anonfun$main$1
const #22 = Asciz ScalaHelloWorld2;
const #23 = class #22; // ScalaHelloWorld2
const #24 = Asciz $anonfun$main$1;
const #25 = Asciz java/lang/Object;
const #26 = class #25; // java/lang/Object
{
public static final void main(java.lang.String[]);
Code:
Stack=2, Locals=1, Args_size=1
0: getstatic #11; //Field ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
3: aload_0
4: invokevirtual #13; //Method ScalaHelloWorld2$.main:([Ljava/lang/String;)V
7: return
}
ScalaHelloWorld2.class 2.9
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2 extends java.lang.Object
SourceFile: "ScalaHelloWorld2.scala"
ScalaSig: length = 0x3
05 00 00
RuntimeVisibleAnnotations: length = 0xB
00 01 00 0F 00 01 00 10 73 00 11
InnerClass:
public final #21; //class ScalaHelloWorld2$$anonfun$main$1
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz main;
const #4 = Asciz ([Ljava/lang/String;)V;
const #5 = Asciz Code;
const #6 = Asciz ScalaHelloWorld2$;
const #7 = class #6; // ScalaHelloWorld2$
const #8 = Asciz MODULE$;
const #9 = Asciz LScalaHelloWorld2$;;
const #10 = NameAndType #8:#9;// MODULE$:LScalaHelloWorld2$;
const #11 = Field #7.#10; // ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
const #12 = NameAndType #3:#4;// main:([Ljava/lang/String;)V
const #13 = Method #7.#12; // ScalaHelloWorld2$.main:([Ljava/lang/String;)V
const #14 = Asciz ScalaSig;
const #15 = Asciz Lscala/reflect/ScalaSignature;;
const #16 = Asciz bytes;
const #17 = Asciz 5:Q!\t\tcU2bYDU\r7p/>H\r\tqP3naRLhh9Q\"!RA!M\r\1IK2dwnV8sY4cA%A1E)QBDYtwMCQM^1\nEa!AB(cUG-5\tACC8-7b\t9BCATGdm2kK$\"B\r\tQAj]&$hFar\"i-8y\tCA\n\tCCV]&$\"B1sON2a'\t)CCABeJ(U91KSQ\ta:fI4BA-FO]5oO*;
const #18 = Asciz RuntimeVisibleAnnotations;
const #19 = Asciz InnerClasses;
const #20 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #21 = class #20; // ScalaHelloWorld2$$anonfun$main$1
const #22 = Asciz ScalaHelloWorld2;
const #23 = class #22; // ScalaHelloWorld2
const #24 = Asciz java/lang/Object;
const #25 = class #24; // java/lang/Object
{
public static final void main(java.lang.String[]);
Code:
Stack=2, Locals=1, Args_size=1
0: getstatic #11; //Field ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
3: aload_0
4: invokevirtual #13; //Method ScalaHelloWorld2$.main:([Ljava/lang/String;)V
7: return
}
ScalaHelloWorld2$.class 2.8
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2$ extends java.lang.Object implements scala.ScalaObject
SourceFile: "ScalaHelloWorld2.scala"
Scala: length = 0x
InnerClass:
public final #41= #22 of #40; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz MODULE$;
const #4 = Asciz LScalaHelloWorld2$;;
const #5 = Asciz <clinit>;
const #6 = Asciz ()V;
const #7 = Asciz Code;
const #8 = Asciz ScalaHelloWorld2$;
const #9 = class #8; // ScalaHelloWorld2$
const #10 = Asciz <init>;
const #11 = NameAndType #10:#6;// "<init>":()V
const #12 = Method #9.#11; // ScalaHelloWorld2$."<init>":()V
const #13 = Asciz main;
const #14 = Asciz ([Ljava/lang/String;)V;
const #15 = Asciz eu/teraflux/uniman/transactions/TMLib$;
const #16 = class #15; // eu/teraflux/uniman/transactions/TMLib$
const #17 = Asciz Leu/teraflux/uniman/transactions/TMLib$;;
const #18 = NameAndType #3:#17;// MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
const #19 = Field #16.#18; // eu/teraflux/uniman/transactions/TMLib$.MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
const #20 = Asciz LineNumberTable;
const #21 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #22 = class #21; // ScalaHelloWorld2$$anonfun$main$1
const #23 = Method #22.#11; // ScalaHelloWorld2$$anonfun$main$1."<init>":()V
const #24 = Asciz atomic;
const #25 = Asciz (Lscala/Function1;)V;
const #26 = NameAndType #24:#25;// atomic:(Lscala/Function1;)V
const #27 = Method #16.#26; // eu/teraflux/uniman/transactions/TMLib$.atomic:(Lscala/Function1;)V
const #28 = Asciz this;
const #29 = Asciz args;
const #30 = Asciz [Ljava/lang/String;;
const #31 = Asciz LocalVariableTable;
const #32 = Asciz java/lang/Object;
const #33 = class #32; // java/lang/Object
const #34 = Method #33.#11; // java/lang/Object."<init>":()V
const #35 = NameAndType #3:#4;// MODULE$:LScalaHelloWorld2$;
const #36 = Field #9.#35; // ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
const #37 = Asciz Scala;
const #38 = Asciz InnerClasses;
const #39 = Asciz ScalaHelloWorld2;
const #40 = class #39; // ScalaHelloWorld2
const #41 = Asciz $anonfun$main$1;
const #42 = Asciz scala/ScalaObject;
const #43 = class #42; // scala/ScalaObject
{
public static final ScalaHelloWorld2$ MODULE$;
public static {};
Code:
Stack=1, Locals=0, Args_size=0
0: new #9; //class ScalaHelloWorld2$
3: invokespecial #12; //Method "<init>":()V
6: return
public void main(java.lang.String[]);
Code:
Stack=3, Locals=2, Args_size=2
0: getstatic #19; //Field eu/teraflux/uniman/transactions/TMLib$.MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
3: new #22; //class ScalaHelloWorld2$$anonfun$main$1
6: dup
7: invokespecial #23; //Method ScalaHelloWorld2$$anonfun$main$1."<init>":()V
10: invokevirtual #27; //Method eu/teraflux/uniman/transactions/TMLib$.atomic:(Lscala/Function1;)V
13: return
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 14 0 this LScalaHelloWorld2$;
0 14 1 args [Ljava/lang/String;
}
ScalaHelloWorld2$.class 2.9
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2$ extends java.lang.Object implements scala.ScalaObject
SourceFile: "ScalaHelloWorld2.scala"
Scala: length = 0x
InnerClass:
public final #22; //class ScalaHelloWorld2$$anonfun$main$1
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz MODULE$;
const #4 = Asciz LScalaHelloWorld2$;;
const #5 = Asciz <clinit>;
const #6 = Asciz ()V;
const #7 = Asciz Code;
const #8 = Asciz ScalaHelloWorld2$;
const #9 = class #8; // ScalaHelloWorld2$
const #10 = Asciz <init>;
const #11 = NameAndType #10:#6;// "<init>":()V
const #12 = Method #9.#11; // ScalaHelloWorld2$."<init>":()V
const #13 = Asciz main;
const #14 = Asciz ([Ljava/lang/String;)V;
const #15 = Asciz eu/teraflux/uniman/transactions/TMLib$;
const #16 = class #15; // eu/teraflux/uniman/transactions/TMLib$
const #17 = Asciz Leu/teraflux/uniman/transactions/TMLib$;;
const #18 = NameAndType #3:#17;// MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
const #19 = Field #16.#18; // eu/teraflux/uniman/transactions/TMLib$.MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
const #20 = Asciz LineNumberTable;
const #21 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #22 = class #21; // ScalaHelloWorld2$$anonfun$main$1
const #23 = Method #22.#11; // ScalaHelloWorld2$$anonfun$main$1."<init>":()V
const #24 = Asciz atomic;
const #25 = Asciz (Lscala/Function1;)V;
const #26 = NameAndType #24:#25;// atomic:(Lscala/Function1;)V
const #27 = Method #16.#26; // eu/teraflux/uniman/transactions/TMLib$.atomic:(Lscala/Function1;)V
const #28 = Asciz this;
const #29 = Asciz args;
const #30 = Asciz [Ljava/lang/String;;
const #31 = Asciz LocalVariableTable;
const #32 = Asciz java/lang/Object;
const #33 = class #32; // java/lang/Object
const #34 = Method #33.#11; // java/lang/Object."<init>":()V
const #35 = NameAndType #3:#4;// MODULE$:LScalaHelloWorld2$;
const #36 = Field #9.#35; // ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
const #37 = Asciz Scala;
const #38 = Asciz InnerClasses;
const #39 = Asciz scala/ScalaObject;
const #40 = class #39; // scala/ScalaObject
{
public static final ScalaHelloWorld2$ MODULE$;
public static {};
Code:
Stack=1, Locals=0, Args_size=0
0: new #9; //class ScalaHelloWorld2$
3: invokespecial #12; //Method "<init>":()V
6: return
public void main(java.lang.String[]);
Code:
Stack=3, Locals=2, Args_size=2
0: getstatic #19; //Field eu/teraflux/uniman/transactions/TMLib$.MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
3: new #22; //class ScalaHelloWorld2$$anonfun$main$1
6: dup
7: invokespecial #23; //Method ScalaHelloWorld2$$anonfun$main$1."<init>":()V
10: invokevirtual #27; //Method eu/teraflux/uniman/transactions/TMLib$.atomic:(Lscala/Function1;)V
13: return
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 14 0 this LScalaHelloWorld2$;
0 14 1 args [Ljava/lang/String;
}
ScalaHelloWorld2$$anonfun$main$1.class 2.8
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2$$anonfun$main$1 extends scala.runtime.AbstractFunction1 implements java.io.Serializable
SourceFile: "ScalaHelloWorld2.scala"
Scala: length = 0x
InnerClass:
public final #51= #9 of #50; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz <clinit>;
const #4 = Asciz ()V;
const #5 = Asciz Code;
const #6 = Asciz serialVersionUID;
const #7 = Asciz J;
const #8 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #9 = class #8; // ScalaHelloWorld2$$anonfun$main$1
const #10 = NameAndType #6:#7;// serialVersionUID:J
const #11 = Field #9.#10; // ScalaHelloWorld2$$anonfun$main$1.serialVersionUID:J
const #12 = Asciz apply;
const #13 = Asciz (Lscala/runtime/BoxedUnit;)V;
const #14 = Asciz scala/Predef$;
const #15 = class #14; // scala/Predef$
const #16 = Asciz MODULE$;
const #17 = Asciz Lscala/Predef$;;
const #18 = NameAndType #16:#17;// MODULE$:Lscala/Predef$;
const #19 = Field #15.#18; // scala/Predef$.MODULE$:Lscala/Predef$;
const #20 = Asciz LineNumberTable;
const #21 = Asciz Hello World from Scala;
const #22 = String #21; // Hello World from Scala
const #23 = Asciz println;
const #24 = Asciz (Ljava/lang/Object;)V;
const #25 = NameAndType #23:#24;// println:(Ljava/lang/Object;)V
const #26 = Method #15.#25; // scala/Predef$.println:(Ljava/lang/Object;)V
const #27 = Asciz this;
const #28 = Asciz LScalaHelloWorld2$$anonfun$main$1;;
const #29 = Asciz Unit;
const #30 = Asciz Lscala/runtime/BoxedUnit;;
const #31 = Asciz LocalVariableTable;
const #32 = Asciz (Ljava/lang/Object;)Ljava/lang/Object;;
const #33 = Asciz scala/runtime/BoxedUnit;
const #34 = class #33; // scala/runtime/BoxedUnit
const #35 = NameAndType #12:#13;// apply:(Lscala/runtime/BoxedUnit;)V
const #36 = Method #9.#35; // ScalaHelloWorld2$$anonfun$main$1.apply:(Lscala/runtime/BoxedUnit;)V
const #37 = Asciz UNIT;
const #38 = NameAndType #37:#30;// UNIT:Lscala/runtime/BoxedUnit;
const #39 = Field #34.#38; // scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
const #40 = Asciz v1;
const #41 = Asciz Ljava/lang/Object;;
const #42 = Asciz <init>;
const #43 = Asciz scala/runtime/AbstractFunction1;
const #44 = class #43; // scala/runtime/AbstractFunction1
const #45 = NameAndType #42:#4;// "<init>":()V
const #46 = Method #44.#45; // scala/runtime/AbstractFunction1."<init>":()V
const #47 = Asciz Scala;
const #48 = Asciz InnerClasses;
const #49 = Asciz ScalaHelloWorld2;
const #50 = class #49; // ScalaHelloWorld2
const #51 = Asciz $anonfun$main$1;
const #52 = Asciz java/io/Serializable;
const #53 = class #52; // java/io/Serializable
{
public static final long serialVersionUID;
public static {};
Code:
Stack=2, Locals=0, Args_size=0
0: lconst_0
1: putstatic #11; //Field serialVersionUID:J
4: return
public final void apply(scala.runtime.BoxedUnit);
Code:
Stack=2, Locals=2, Args_size=2
0: getstatic #19; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: ldc #22; //String Hello World from Scala
5: invokevirtual #26; //Method scala/Predef$.println:(Ljava/lang/Object;)V
8: return
LineNumberTable:
line 5: 0
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this LScalaHelloWorld2$$anonfun$main$1;
0 9 1 Unit Lscala/runtime/BoxedUnit;
public final java.lang.Object apply(java.lang.Object);
Code:
Stack=2, Locals=2, Args_size=2
0: aload_0
1: aload_1
2: checkcast #34; //class scala/runtime/BoxedUnit
5: invokevirtual #36; //Method apply:(Lscala/runtime/BoxedUnit;)V
8: getstatic #39; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
11: areturn
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 12 0 this LScalaHelloWorld2$$anonfun$main$1;
0 12 1 v1 Ljava/lang/Object;
public ScalaHelloWorld2$$anonfun$main$1();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #46; //Method scala/runtime/AbstractFunction1."<init>":()V
4: return
LineNumberTable:
line 4: 0
}
ScalaHelloWorld2$$anonfun$main$1.class 2.9
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2$$anonfun$main$1 extends scala.runtime.AbstractFunction1 implements scala.Serializable
SourceFile: "ScalaHelloWorld2.scala"
Scala: length = 0x
EnclosingMethod: length = 0x4
00 32 00 35
InnerClass:
public final #9; //class ScalaHelloWorld2$$anonfun$main$1
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz <clinit>;
const #4 = Asciz ()V;
const #5 = Asciz Code;
const #6 = Asciz serialVersionUID;
const #7 = Asciz J;
const #8 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #9 = class #8; // ScalaHelloWorld2$$anonfun$main$1
const #10 = NameAndType #6:#7;// serialVersionUID:J
const #11 = Field #9.#10; // ScalaHelloWorld2$$anonfun$main$1.serialVersionUID:J
const #12 = Asciz apply;
const #13 = Asciz (Lscala/runtime/BoxedUnit;)V;
const #14 = Asciz scala/Predef$;
const #15 = class #14; // scala/Predef$
const #16 = Asciz MODULE$;
const #17 = Asciz Lscala/Predef$;;
const #18 = NameAndType #16:#17;// MODULE$:Lscala/Predef$;
const #19 = Field #15.#18; // scala/Predef$.MODULE$:Lscala/Predef$;
const #20 = Asciz LineNumberTable;
const #21 = Asciz Hello World from Scala;
const #22 = String #21; // Hello World from Scala
const #23 = Asciz println;
const #24 = Asciz (Ljava/lang/Object;)V;
const #25 = NameAndType #23:#24;// println:(Ljava/lang/Object;)V
const #26 = Method #15.#25; // scala/Predef$.println:(Ljava/lang/Object;)V
const #27 = Asciz this;
const #28 = Asciz LScalaHelloWorld2$$anonfun$main$1;;
const #29 = Asciz Unit;
const #30 = Asciz Lscala/runtime/BoxedUnit;;
const #31 = Asciz LocalVariableTable;
const #32 = Asciz (Ljava/lang/Object;)Ljava/lang/Object;;
const #33 = Asciz scala/runtime/BoxedUnit;
const #34 = class #33; // scala/runtime/BoxedUnit
const #35 = NameAndType #12:#13;// apply:(Lscala/runtime/BoxedUnit;)V
const #36 = Method #9.#35; // ScalaHelloWorld2$$anonfun$main$1.apply:(Lscala/runtime/BoxedUnit;)V
const #37 = Asciz UNIT;
const #38 = NameAndType #37:#30;// UNIT:Lscala/runtime/BoxedUnit;
const #39 = Field #34.#38; // scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
const #40 = Asciz v1;
const #41 = Asciz Ljava/lang/Object;;
const #42 = Asciz <init>;
const #43 = Asciz scala/runtime/AbstractFunction1;
const #44 = class #43; // scala/runtime/AbstractFunction1
const #45 = NameAndType #42:#4;// "<init>":()V
const #46 = Method #44.#45; // scala/runtime/AbstractFunction1."<init>":()V
const #47 = Asciz Scala;
const #48 = Asciz EnclosingMethod;
const #49 = Asciz ScalaHelloWorld2$;
const #50 = class #49; // ScalaHelloWorld2$
const #51 = Asciz main;
const #52 = Asciz ([Ljava/lang/String;)V;
const #53 = NameAndType #51:#52;// main:([Ljava/lang/String;)V
const #54 = Asciz InnerClasses;
const #55 = Asciz scala/Serializable;
const #56 = class #55; // scala/Serializable
{
public static final long serialVersionUID;
public static {};
Code:
Stack=4, Locals=0, Args_size=0
0: lconst_0
1: lconst_0
2: putstatic #11; //Field serialVersionUID:J
5: return
public final void apply(scala.runtime.BoxedUnit);
Code:
Stack=2, Locals=2, Args_size=2
0: getstatic #19; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: ldc #22; //String Hello World from Scala
5: invokevirtual #26; //Method scala/Predef$.println:(Ljava/lang/Object;)V
8: return
LineNumberTable:
line 5: 0
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this LScalaHelloWorld2$$anonfun$main$1;
0 9 1 Unit Lscala/runtime/BoxedUnit;
public final java.lang.Object apply(java.lang.Object);
Code:
Stack=2, Locals=2, Args_size=2
0: aload_0
1: aload_1
2: checkcast #34; //class scala/runtime/BoxedUnit
5: invokevirtual #36; //Method apply:(Lscala/runtime/BoxedUnit;)V
8: getstatic #39; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
11: areturn
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 12 0 this LScalaHelloWorld2$$anonfun$main$1;
0 12 1 v1 Ljava/lang/Object;
public ScalaHelloWorld2$$anonfun$main$1();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #46; //Method scala/runtime/AbstractFunction1."<init>":()V
4: return
LineNumberTable:
line 4: 0
}
On 11/07/11 15:27, Daniel Goodman wrote:4E1B086B [dot] 4080701 [at] cs [dot] man [dot] ac [dot] uk" type="cite"> Hi Martin,
Thanks for getting back to me. My code does not use the Java Signature attribute, so I am relatively sure that this is no the cause. However I will keep narrowing this down and try to come back to you in with more specific questions. In the mean time if anyone else has any thoughts I would love to hear from you.
All the best
Daniel
On 09/07/11 13:19, martin odersky wrote:dhP8VCkidF9kdpy0w [at] mail [dot] gmail [dot] com" type="cite">One change which might be relevant is that Java generic signatures have changed between 2.8 and 2.9. 2.8 generated sometimes incorrect signatures for Java generics. These have changed in 2.9. So if you code depends on the JavaSignature attribute it needs to be updated.
Cheers
-- Martin
On Sat, Jul 9, 2011 at 12:28 PM, Daniel Goodman <goodmand [at] cs [dot] man [dot] ac [dot] uk" rel="nofollow">goodmand@cs.man.ac.uk> wrote:
Hi,
I tried sending this to Scala users and got no takers, so given it is related to the internals of the system I thought I would give this list a try. I hope this is ok.
I have a problem with a change in the behaviour of Scala between version 2.9 and the earlier versions, and am hoping someone can save me some time by pointing me in the correct direction for solving it.
I'm building various Transactional Memory solutions for Scala. These are based on the Deuce STM approach of using Java Agents to perform a byte code rewrite at run time. This rewrite creates instrumented duplicates of the methods that appear in the classes. These duplicates can then be used to execute sections of code transactionally. This is done in conjunction with additionally created classes that hold information about the positions of fields within the original classes.
So far so good, and this all works fine with Scala 2.7 and 2.8, the problems arises with Scala 2.9. When trying to use this system under 2.9 the program fails with depending on which of my TM set-ups I'm using a field or a method not found exception. In both cases these are fields or methods that should have been added by the Java Agent. It would appear that the code that the JVM is seeing at this point has not been extended by the Java Agent. The addition of print statements confirms that the Java Agent is running for the classes required. The fact that the program is trying to access the fields that are only inserted by the Java Agent shows that at least some of the rewritten code is being executed. Examining the compiled Scala code shows no obvious changes for the files in question between 2.7 and 2.9. Running the Java Agent on the code outside of the runtime environment produces the correct rewritten code. All of these tests have been performed with the same JVM. Does anyone have any thoughts on what has changed between 2.8 and 2.9 that would cause this error? Is there some new verification of class signatures?
Many thanks in advance
Daniel
--
Martin Odersky
Prof., EPFL and Chairman, Typesafe
PSED, 1015 Lausanne, Switzerland
Tel. EPFL: +41 21 693 6863
Tel. Typesafe: +41 21 691 4967
Thu, 2011-07-14, 10:47
#5
Re: Change of behaviour between Scala2.[7-8] and 2.9 when using
Ok,
So to answer answer two of my own questions, scala.Serializable was only used in the closure and the closure was only used in the atomic code. So from this, clearly 2.9 code is not backwards compatible with 2.8!
This still leaves me with the question of why the rewritten code is rejected by scala 2.9. As smaller questions on the way, could anyone tell me what functionallity is added by the argument -Xbootclasspath/a:/usr/share/scala/lib/scala-library.jar in the 2.9 scala command?
Does this overriding of the classes add in extra checking that uses the Scala signature at run time?
Any takers for these?
Many thanks
Daniel
On 13/07/11 17:56, Daniel Goodman wrote:
So to answer answer two of my own questions, scala.Serializable was only used in the closure and the closure was only used in the atomic code. So from this, clearly 2.9 code is not backwards compatible with 2.8!
This still leaves me with the question of why the rewritten code is rejected by scala 2.9. As smaller questions on the way, could anyone tell me what functionallity is added by the argument -Xbootclasspath/a:/usr/share/scala/lib/scala-library.jar in the 2.9 scala command?
Does this overriding of the classes add in extra checking that uses the Scala signature at run time?
Any takers for these?
Many thanks
Daniel
On 13/07/11 17:56, Daniel Goodman wrote:
4E1DCE57 [dot] 2060003 [at] cs [dot] man [dot] ac [dot] uk" type="cite"> Hi,
So on further investigation I realised that scala.Serializable is not actually part of the 2.8 libraries. Taking the source from the 2.9 library, compiling it with the 2.8 compiler and inserting it into the scala-library jar files overcomes the problem of running 2.9 code on the 2.8 scala command. This does still leave me with two questions about the 2.8 runtime.
1. Is Scala 2.9 code meant to not be compatible with the Scala 2.8 runtime?
2. Why didn't the 2.8 runtime try to load scala.Serializable when the byte-code was in its original form? This would seem to be an error.
For the 2.9 Runtime, I am still unsure why it is failing to find code I know the java agent is producing. Does the -Xbootclasspath/a argument change the class loader?
Daniel
On 13/07/11 16:48, Daniel Goodman wrote:4E1DBE67 [dot] 6030903 [at] cs [dot] man [dot] ac [dot] uk" type="cite"> Hi,
So I am still trying to narrow down the cause of this issue. Experimenting with a specific case showed that running 2.8 or 2.9 code on the 2.9 version of scala throws a method not found exception when the code tried to access a new method added by the byte code rewrite. Running these versions against the 2.8 version of scala, the files compiled with the 2.8 version of scalac worked, but the ones compiled with the 2.9 version failed with a java.lang.NoClassDefFound Error. This appeared to be being thrown by the class loader. As this gave me a small piece of code to examine, where one version worked and one did not I decided to start examining the code here.
Examining the byte code shows that byte code instructions that make up the different methods are identical. This would appear to mean that it is the way the runtime environment uses the remaining meta-data in the class that is making the difference. To try and isolate this first I tried to strip back the command used in scala such that the code was running directly on the JVM rather than in an augmented runtime. However the closest I could get is as follows:
2.8
java -javaagent:muts_2.8.jar -cp /usr/scala-2.8.1.final/lib/scala-compiler.jar:/usr/scala-2.8.1.final/lib/scala-library.jar -Dscala.home=/usr/scala-2.8.1.final scala.tools.nsc.MainGenericRunner -cp .:./muts_2.8.jar ScalaHelloWorld
2.9
java -javaagent:muts_2.8.jar -cp muts_2.8.jar:. -Xbootclasspath/a:/usr/share/scala/lib/scala-library.jar ScalaHelloWorld
This would appear to show that Scala class files require an augmented runtime to execute. So the first questions are: Can I run scala code without either using an additional program or changing classes in the JVM? Secondly, in each of these cases what is the augmented functionality?
Next I looked at the fields in more detail: the code I compiled was:
import eu.teraflux.uniman.transactions.TMLib._
object ScalaHelloWorld2 {
def main(args:Array[String]) {
atomic{ Unit =>
println("Hello World from Scala")
}
}
}
which results in the three bytecode files being produced: ScalaHelloWorld2.class; ScalaHelloWorld2$.class and ScalaHelloWorld2$$anonfun$main$1.class. According to JavaP the differences between these classes are as follows.
ScalaHelloWorld2.class
2.8 contains
InnerClass:
public final #24= #21 of #23; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
which becomes
InnerClass:
public final #21; //class ScalaHelloWorld2$$anonfun$main$1
in 2.9.
The scala signatures are also different, 2.8 is
const #17 = Asciz 5:Q!\t\tcU2bYDU\r7p/>H\r\tqP3naRLhh9Q\"!A!A\t%cU2bYDU\r7p/>HQ!!5\tAB!A.8hy6bmL!!\r='.Z2u!\tb#D)!B:dC2BA-6-7b\nTWm;\te9A\rqJg.;?))\"\tiB7bS:$\"AHMyB)f.;\t\tZA\txm\t'2BA\t%O]1z!\t9#FQ%F!J,G-4\n-b#AB*ue&twM*);
and 2.9 is
const #17 = Asciz 5:Q!\t\tcU2bYDU\r7p/>H\r\tqP3naRLhh9Q\"!RA!M\r\1IK2dwnV8sY4cA%A1E)QBDYtwMCQM^1\nEa!AB(cUG-5\tACC8-7b\t9BCATGdm2kK$\"B\r\tQAj]&$hFar\"i-8y\tCA\n\tCCV]&$\"B1sON2a'\t)CCABeJ(U91KSQ\ta:fI4BA-FO]5oO*;
finally 2.8 also contains the following extra constant
const #24 = Asciz java/lang/Object;
ScalaHelloWorld2$.class
2.8 contains
InnerClass:
public final #41= #22 of #40; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
which becomes
InnerClass:
public final #22; //class ScalaHelloWorld2$$anonfun$main$1
in 2.9. 2.8 also contains the following extra constants
const #39 = Asciz ScalaHelloWorld2;
const #40 = class #39; // ScalaHelloWorld2
const #41 = Asciz $anonfun$main$1;
ScalaHelloWorld2$$anonfun$main$1.class
Finally
the 2.8 headers change from
InnerClass:
public final #51= #9 of #50; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
to
EnclosingMethod: length = 0x4
00 32 00 35
InnerClass:
public final #9; //class ScalaHelloWorld2$$anonfun$main$1
and the interface implemented changes from java.io.Serializable to scala.Serializable
I have included the full text of each of the methods at the end of the email incase I have missed out an important detail here. My last question is as my rewrite does not change any of these values, but augments the constant pool with additional values to support the additional instrumented methods, is anyone aware of what in these changes is causing the re-writen code to fail for the 2.9 code, but not for the 2.8 code?
Many thanks in advance
Daniel
ScalaHelloWorld2.class 2.8
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2 extends java.lang.Object
SourceFile: "ScalaHelloWorld2.scala"
ScalaSig: length = 0x3
05 00 00
RuntimeVisibleAnnotations: length = 0xB
00 01 00 0F 00 01 00 10 73 00 11
InnerClass:
public final #24= #21 of #23; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz main;
const #4 = Asciz ([Ljava/lang/String;)V;
const #5 = Asciz Code;
const #6 = Asciz ScalaHelloWorld2$;
const #7 = class #6; // ScalaHelloWorld2$
const #8 = Asciz MODULE$;
const #9 = Asciz LScalaHelloWorld2$;;
const #10 = NameAndType #8:#9;// MODULE$:LScalaHelloWorld2$;
const #11 = Field #7.#10; // ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
const #12 = NameAndType #3:#4;// main:([Ljava/lang/String;)V
const #13 = Method #7.#12; // ScalaHelloWorld2$.main:([Ljava/lang/String;)V
const #14 = Asciz ScalaSig;
const #15 = Asciz Lscala/reflect/ScalaSignature;;
const #16 = Asciz bytes;
const #17 = Asciz 5:Q!\t\tcU2bYDU\r7p/>H\r\tqP3naRLhh9Q\"!A!A\t%cU2bYDU\r7p/>HQ!!5\tAB!A.8hy6bmL!!\r='.Z2u!\tb#D)!B:dC2BA-6-7b\nTWm;\te9A\rqJg.;?))\"\tiB7bS:$\"AHMyB)f.;\t\tZA\txm\t'2BA\t%O]1z!\t9#FQ%F!J,G-4\n-b#AB*ue&twM*);
const #18 = Asciz RuntimeVisibleAnnotations;
const #19 = Asciz InnerClasses;
const #20 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #21 = class #20; // ScalaHelloWorld2$$anonfun$main$1
const #22 = Asciz ScalaHelloWorld2;
const #23 = class #22; // ScalaHelloWorld2
const #24 = Asciz $anonfun$main$1;
const #25 = Asciz java/lang/Object;
const #26 = class #25; // java/lang/Object
{
public static final void main(java.lang.String[]);
Code:
Stack=2, Locals=1, Args_size=1
0: getstatic #11; //Field ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
3: aload_0
4: invokevirtual #13; //Method ScalaHelloWorld2$.main:([Ljava/lang/String;)V
7: return
}
ScalaHelloWorld2.class 2.9
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2 extends java.lang.Object
SourceFile: "ScalaHelloWorld2.scala"
ScalaSig: length = 0x3
05 00 00
RuntimeVisibleAnnotations: length = 0xB
00 01 00 0F 00 01 00 10 73 00 11
InnerClass:
public final #21; //class ScalaHelloWorld2$$anonfun$main$1
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz main;
const #4 = Asciz ([Ljava/lang/String;)V;
const #5 = Asciz Code;
const #6 = Asciz ScalaHelloWorld2$;
const #7 = class #6; // ScalaHelloWorld2$
const #8 = Asciz MODULE$;
const #9 = Asciz LScalaHelloWorld2$;;
const #10 = NameAndType #8:#9;// MODULE$:LScalaHelloWorld2$;
const #11 = Field #7.#10; // ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
const #12 = NameAndType #3:#4;// main:([Ljava/lang/String;)V
const #13 = Method #7.#12; // ScalaHelloWorld2$.main:([Ljava/lang/String;)V
const #14 = Asciz ScalaSig;
const #15 = Asciz Lscala/reflect/ScalaSignature;;
const #16 = Asciz bytes;
const #17 = Asciz 5:Q!\t\tcU2bYDU\r7p/>H\r\tqP3naRLhh9Q\"!RA!M\r\1IK2dwnV8sY4cA%A1E)QBDYtwMCQM^1\nEa!AB(cUG-5\tACC8-7b\t9BCATGdm2kK$\"B\r\tQAj]&$hFar\"i-8y\tCA\n\tCCV]&$\"B1sON2a'\t)CCABeJ(U91KSQ\ta:fI4BA-FO]5oO*;
const #18 = Asciz RuntimeVisibleAnnotations;
const #19 = Asciz InnerClasses;
const #20 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #21 = class #20; // ScalaHelloWorld2$$anonfun$main$1
const #22 = Asciz ScalaHelloWorld2;
const #23 = class #22; // ScalaHelloWorld2
const #24 = Asciz java/lang/Object;
const #25 = class #24; // java/lang/Object
{
public static final void main(java.lang.String[]);
Code:
Stack=2, Locals=1, Args_size=1
0: getstatic #11; //Field ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
3: aload_0
4: invokevirtual #13; //Method ScalaHelloWorld2$.main:([Ljava/lang/String;)V
7: return
}
ScalaHelloWorld2$.class 2.8
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2$ extends java.lang.Object implements scala.ScalaObject
SourceFile: "ScalaHelloWorld2.scala"
Scala: length = 0x
InnerClass:
public final #41= #22 of #40; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz MODULE$;
const #4 = Asciz LScalaHelloWorld2$;;
const #5 = Asciz <clinit>;
const #6 = Asciz ()V;
const #7 = Asciz Code;
const #8 = Asciz ScalaHelloWorld2$;
const #9 = class #8; // ScalaHelloWorld2$
const #10 = Asciz <init>;
const #11 = NameAndType #10:#6;// "<init>":()V
const #12 = Method #9.#11; // ScalaHelloWorld2$."<init>":()V
const #13 = Asciz main;
const #14 = Asciz ([Ljava/lang/String;)V;
const #15 = Asciz eu/teraflux/uniman/transactions/TMLib$;
const #16 = class #15; // eu/teraflux/uniman/transactions/TMLib$
const #17 = Asciz Leu/teraflux/uniman/transactions/TMLib$;;
const #18 = NameAndType #3:#17;// MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
const #19 = Field #16.#18; // eu/teraflux/uniman/transactions/TMLib$.MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
const #20 = Asciz LineNumberTable;
const #21 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #22 = class #21; // ScalaHelloWorld2$$anonfun$main$1
const #23 = Method #22.#11; // ScalaHelloWorld2$$anonfun$main$1."<init>":()V
const #24 = Asciz atomic;
const #25 = Asciz (Lscala/Function1;)V;
const #26 = NameAndType #24:#25;// atomic:(Lscala/Function1;)V
const #27 = Method #16.#26; // eu/teraflux/uniman/transactions/TMLib$.atomic:(Lscala/Function1;)V
const #28 = Asciz this;
const #29 = Asciz args;
const #30 = Asciz [Ljava/lang/String;;
const #31 = Asciz LocalVariableTable;
const #32 = Asciz java/lang/Object;
const #33 = class #32; // java/lang/Object
const #34 = Method #33.#11; // java/lang/Object."<init>":()V
const #35 = NameAndType #3:#4;// MODULE$:LScalaHelloWorld2$;
const #36 = Field #9.#35; // ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
const #37 = Asciz Scala;
const #38 = Asciz InnerClasses;
const #39 = Asciz ScalaHelloWorld2;
const #40 = class #39; // ScalaHelloWorld2
const #41 = Asciz $anonfun$main$1;
const #42 = Asciz scala/ScalaObject;
const #43 = class #42; // scala/ScalaObject
{
public static final ScalaHelloWorld2$ MODULE$;
public static {};
Code:
Stack=1, Locals=0, Args_size=0
0: new #9; //class ScalaHelloWorld2$
3: invokespecial #12; //Method "<init>":()V
6: return
public void main(java.lang.String[]);
Code:
Stack=3, Locals=2, Args_size=2
0: getstatic #19; //Field eu/teraflux/uniman/transactions/TMLib$.MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
3: new #22; //class ScalaHelloWorld2$$anonfun$main$1
6: dup
7: invokespecial #23; //Method ScalaHelloWorld2$$anonfun$main$1."<init>":()V
10: invokevirtual #27; //Method eu/teraflux/uniman/transactions/TMLib$.atomic:(Lscala/Function1;)V
13: return
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 14 0 this LScalaHelloWorld2$;
0 14 1 args [Ljava/lang/String;
}
ScalaHelloWorld2$.class 2.9
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2$ extends java.lang.Object implements scala.ScalaObject
SourceFile: "ScalaHelloWorld2.scala"
Scala: length = 0x
InnerClass:
public final #22; //class ScalaHelloWorld2$$anonfun$main$1
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz MODULE$;
const #4 = Asciz LScalaHelloWorld2$;;
const #5 = Asciz <clinit>;
const #6 = Asciz ()V;
const #7 = Asciz Code;
const #8 = Asciz ScalaHelloWorld2$;
const #9 = class #8; // ScalaHelloWorld2$
const #10 = Asciz <init>;
const #11 = NameAndType #10:#6;// "<init>":()V
const #12 = Method #9.#11; // ScalaHelloWorld2$."<init>":()V
const #13 = Asciz main;
const #14 = Asciz ([Ljava/lang/String;)V;
const #15 = Asciz eu/teraflux/uniman/transactions/TMLib$;
const #16 = class #15; // eu/teraflux/uniman/transactions/TMLib$
const #17 = Asciz Leu/teraflux/uniman/transactions/TMLib$;;
const #18 = NameAndType #3:#17;// MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
const #19 = Field #16.#18; // eu/teraflux/uniman/transactions/TMLib$.MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
const #20 = Asciz LineNumberTable;
const #21 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #22 = class #21; // ScalaHelloWorld2$$anonfun$main$1
const #23 = Method #22.#11; // ScalaHelloWorld2$$anonfun$main$1."<init>":()V
const #24 = Asciz atomic;
const #25 = Asciz (Lscala/Function1;)V;
const #26 = NameAndType #24:#25;// atomic:(Lscala/Function1;)V
const #27 = Method #16.#26; // eu/teraflux/uniman/transactions/TMLib$.atomic:(Lscala/Function1;)V
const #28 = Asciz this;
const #29 = Asciz args;
const #30 = Asciz [Ljava/lang/String;;
const #31 = Asciz LocalVariableTable;
const #32 = Asciz java/lang/Object;
const #33 = class #32; // java/lang/Object
const #34 = Method #33.#11; // java/lang/Object."<init>":()V
const #35 = NameAndType #3:#4;// MODULE$:LScalaHelloWorld2$;
const #36 = Field #9.#35; // ScalaHelloWorld2$.MODULE$:LScalaHelloWorld2$;
const #37 = Asciz Scala;
const #38 = Asciz InnerClasses;
const #39 = Asciz scala/ScalaObject;
const #40 = class #39; // scala/ScalaObject
{
public static final ScalaHelloWorld2$ MODULE$;
public static {};
Code:
Stack=1, Locals=0, Args_size=0
0: new #9; //class ScalaHelloWorld2$
3: invokespecial #12; //Method "<init>":()V
6: return
public void main(java.lang.String[]);
Code:
Stack=3, Locals=2, Args_size=2
0: getstatic #19; //Field eu/teraflux/uniman/transactions/TMLib$.MODULE$:Leu/teraflux/uniman/transactions/TMLib$;
3: new #22; //class ScalaHelloWorld2$$anonfun$main$1
6: dup
7: invokespecial #23; //Method ScalaHelloWorld2$$anonfun$main$1."<init>":()V
10: invokevirtual #27; //Method eu/teraflux/uniman/transactions/TMLib$.atomic:(Lscala/Function1;)V
13: return
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 14 0 this LScalaHelloWorld2$;
0 14 1 args [Ljava/lang/String;
}
ScalaHelloWorld2$$anonfun$main$1.class 2.8
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2$$anonfun$main$1 extends scala.runtime.AbstractFunction1 implements java.io.Serializable
SourceFile: "ScalaHelloWorld2.scala"
Scala: length = 0x
InnerClass:
public final #51= #9 of #50; //$anonfun$main$1=class ScalaHelloWorld2$$anonfun$main$1 of class ScalaHelloWorld2
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz <clinit>;
const #4 = Asciz ()V;
const #5 = Asciz Code;
const #6 = Asciz serialVersionUID;
const #7 = Asciz J;
const #8 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #9 = class #8; // ScalaHelloWorld2$$anonfun$main$1
const #10 = NameAndType #6:#7;// serialVersionUID:J
const #11 = Field #9.#10; // ScalaHelloWorld2$$anonfun$main$1.serialVersionUID:J
const #12 = Asciz apply;
const #13 = Asciz (Lscala/runtime/BoxedUnit;)V;
const #14 = Asciz scala/Predef$;
const #15 = class #14; // scala/Predef$
const #16 = Asciz MODULE$;
const #17 = Asciz Lscala/Predef$;;
const #18 = NameAndType #16:#17;// MODULE$:Lscala/Predef$;
const #19 = Field #15.#18; // scala/Predef$.MODULE$:Lscala/Predef$;
const #20 = Asciz LineNumberTable;
const #21 = Asciz Hello World from Scala;
const #22 = String #21; // Hello World from Scala
const #23 = Asciz println;
const #24 = Asciz (Ljava/lang/Object;)V;
const #25 = NameAndType #23:#24;// println:(Ljava/lang/Object;)V
const #26 = Method #15.#25; // scala/Predef$.println:(Ljava/lang/Object;)V
const #27 = Asciz this;
const #28 = Asciz LScalaHelloWorld2$$anonfun$main$1;;
const #29 = Asciz Unit;
const #30 = Asciz Lscala/runtime/BoxedUnit;;
const #31 = Asciz LocalVariableTable;
const #32 = Asciz (Ljava/lang/Object;)Ljava/lang/Object;;
const #33 = Asciz scala/runtime/BoxedUnit;
const #34 = class #33; // scala/runtime/BoxedUnit
const #35 = NameAndType #12:#13;// apply:(Lscala/runtime/BoxedUnit;)V
const #36 = Method #9.#35; // ScalaHelloWorld2$$anonfun$main$1.apply:(Lscala/runtime/BoxedUnit;)V
const #37 = Asciz UNIT;
const #38 = NameAndType #37:#30;// UNIT:Lscala/runtime/BoxedUnit;
const #39 = Field #34.#38; // scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
const #40 = Asciz v1;
const #41 = Asciz Ljava/lang/Object;;
const #42 = Asciz <init>;
const #43 = Asciz scala/runtime/AbstractFunction1;
const #44 = class #43; // scala/runtime/AbstractFunction1
const #45 = NameAndType #42:#4;// "<init>":()V
const #46 = Method #44.#45; // scala/runtime/AbstractFunction1."<init>":()V
const #47 = Asciz Scala;
const #48 = Asciz InnerClasses;
const #49 = Asciz ScalaHelloWorld2;
const #50 = class #49; // ScalaHelloWorld2
const #51 = Asciz $anonfun$main$1;
const #52 = Asciz java/io/Serializable;
const #53 = class #52; // java/io/Serializable
{
public static final long serialVersionUID;
public static {};
Code:
Stack=2, Locals=0, Args_size=0
0: lconst_0
1: putstatic #11; //Field serialVersionUID:J
4: return
public final void apply(scala.runtime.BoxedUnit);
Code:
Stack=2, Locals=2, Args_size=2
0: getstatic #19; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: ldc #22; //String Hello World from Scala
5: invokevirtual #26; //Method scala/Predef$.println:(Ljava/lang/Object;)V
8: return
LineNumberTable:
line 5: 0
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this LScalaHelloWorld2$$anonfun$main$1;
0 9 1 Unit Lscala/runtime/BoxedUnit;
public final java.lang.Object apply(java.lang.Object);
Code:
Stack=2, Locals=2, Args_size=2
0: aload_0
1: aload_1
2: checkcast #34; //class scala/runtime/BoxedUnit
5: invokevirtual #36; //Method apply:(Lscala/runtime/BoxedUnit;)V
8: getstatic #39; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
11: areturn
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 12 0 this LScalaHelloWorld2$$anonfun$main$1;
0 12 1 v1 Ljava/lang/Object;
public ScalaHelloWorld2$$anonfun$main$1();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #46; //Method scala/runtime/AbstractFunction1."<init>":()V
4: return
LineNumberTable:
line 4: 0
}
ScalaHelloWorld2$$anonfun$main$1.class 2.9
Compiled from "ScalaHelloWorld2.scala"
public final class ScalaHelloWorld2$$anonfun$main$1 extends scala.runtime.AbstractFunction1 implements scala.Serializable
SourceFile: "ScalaHelloWorld2.scala"
Scala: length = 0x
EnclosingMethod: length = 0x4
00 32 00 35
InnerClass:
public final #9; //class ScalaHelloWorld2$$anonfun$main$1
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz ScalaHelloWorld2.scala;
const #3 = Asciz <clinit>;
const #4 = Asciz ()V;
const #5 = Asciz Code;
const #6 = Asciz serialVersionUID;
const #7 = Asciz J;
const #8 = Asciz ScalaHelloWorld2$$anonfun$main$1;
const #9 = class #8; // ScalaHelloWorld2$$anonfun$main$1
const #10 = NameAndType #6:#7;// serialVersionUID:J
const #11 = Field #9.#10; // ScalaHelloWorld2$$anonfun$main$1.serialVersionUID:J
const #12 = Asciz apply;
const #13 = Asciz (Lscala/runtime/BoxedUnit;)V;
const #14 = Asciz scala/Predef$;
const #15 = class #14; // scala/Predef$
const #16 = Asciz MODULE$;
const #17 = Asciz Lscala/Predef$;;
const #18 = NameAndType #16:#17;// MODULE$:Lscala/Predef$;
const #19 = Field #15.#18; // scala/Predef$.MODULE$:Lscala/Predef$;
const #20 = Asciz LineNumberTable;
const #21 = Asciz Hello World from Scala;
const #22 = String #21; // Hello World from Scala
const #23 = Asciz println;
const #24 = Asciz (Ljava/lang/Object;)V;
const #25 = NameAndType #23:#24;// println:(Ljava/lang/Object;)V
const #26 = Method #15.#25; // scala/Predef$.println:(Ljava/lang/Object;)V
const #27 = Asciz this;
const #28 = Asciz LScalaHelloWorld2$$anonfun$main$1;;
const #29 = Asciz Unit;
const #30 = Asciz Lscala/runtime/BoxedUnit;;
const #31 = Asciz LocalVariableTable;
const #32 = Asciz (Ljava/lang/Object;)Ljava/lang/Object;;
const #33 = Asciz scala/runtime/BoxedUnit;
const #34 = class #33; // scala/runtime/BoxedUnit
const #35 = NameAndType #12:#13;// apply:(Lscala/runtime/BoxedUnit;)V
const #36 = Method #9.#35; // ScalaHelloWorld2$$anonfun$main$1.apply:(Lscala/runtime/BoxedUnit;)V
const #37 = Asciz UNIT;
const #38 = NameAndType #37:#30;// UNIT:Lscala/runtime/BoxedUnit;
const #39 = Field #34.#38; // scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
const #40 = Asciz v1;
const #41 = Asciz Ljava/lang/Object;;
const #42 = Asciz <init>;
const #43 = Asciz scala/runtime/AbstractFunction1;
const #44 = class #43; // scala/runtime/AbstractFunction1
const #45 = NameAndType #42:#4;// "<init>":()V
const #46 = Method #44.#45; // scala/runtime/AbstractFunction1."<init>":()V
const #47 = Asciz Scala;
const #48 = Asciz EnclosingMethod;
const #49 = Asciz ScalaHelloWorld2$;
const #50 = class #49; // ScalaHelloWorld2$
const #51 = Asciz main;
const #52 = Asciz ([Ljava/lang/String;)V;
const #53 = NameAndType #51:#52;// main:([Ljava/lang/String;)V
const #54 = Asciz InnerClasses;
const #55 = Asciz scala/Serializable;
const #56 = class #55; // scala/Serializable
{
public static final long serialVersionUID;
public static {};
Code:
Stack=4, Locals=0, Args_size=0
0: lconst_0
1: lconst_0
2: putstatic #11; //Field serialVersionUID:J
5: return
public final void apply(scala.runtime.BoxedUnit);
Code:
Stack=2, Locals=2, Args_size=2
0: getstatic #19; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: ldc #22; //String Hello World from Scala
5: invokevirtual #26; //Method scala/Predef$.println:(Ljava/lang/Object;)V
8: return
LineNumberTable:
line 5: 0
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this LScalaHelloWorld2$$anonfun$main$1;
0 9 1 Unit Lscala/runtime/BoxedUnit;
public final java.lang.Object apply(java.lang.Object);
Code:
Stack=2, Locals=2, Args_size=2
0: aload_0
1: aload_1
2: checkcast #34; //class scala/runtime/BoxedUnit
5: invokevirtual #36; //Method apply:(Lscala/runtime/BoxedUnit;)V
8: getstatic #39; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
11: areturn
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 12 0 this LScalaHelloWorld2$$anonfun$main$1;
0 12 1 v1 Ljava/lang/Object;
public ScalaHelloWorld2$$anonfun$main$1();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #46; //Method scala/runtime/AbstractFunction1."<init>":()V
4: return
LineNumberTable:
line 4: 0
}
On 11/07/11 15:27, Daniel Goodman wrote:4E1B086B [dot] 4080701 [at] cs [dot] man [dot] ac [dot] uk" type="cite"> Hi Martin,
Thanks for getting back to me. My code does not use the Java Signature attribute, so I am relatively sure that this is no the cause. However I will keep narrowing this down and try to come back to you in with more specific questions. In the mean time if anyone else has any thoughts I would love to hear from you.
All the best
Daniel
On 09/07/11 13:19, martin odersky wrote:dhP8VCkidF9kdpy0w [at] mail [dot] gmail [dot] com" type="cite">One change which might be relevant is that Java generic signatures have changed between 2.8 and 2.9. 2.8 generated sometimes incorrect signatures for Java generics. These have changed in 2.9. So if you code depends on the JavaSignature attribute it needs to be updated.
Cheers
-- Martin
On Sat, Jul 9, 2011 at 12:28 PM, Daniel Goodman <goodmand [at] cs [dot] man [dot] ac [dot] uk" rel="nofollow">goodmand@cs.man.ac.uk> wrote:
Hi,
I tried sending this to Scala users and got no takers, so given it is related to the internals of the system I thought I would give this list a try. I hope this is ok.
I have a problem with a change in the behaviour of Scala between version 2.9 and the earlier versions, and am hoping someone can save me some time by pointing me in the correct direction for solving it.
I'm building various Transactional Memory solutions for Scala. These are based on the Deuce STM approach of using Java Agents to perform a byte code rewrite at run time. This rewrite creates instrumented duplicates of the methods that appear in the classes. These duplicates can then be used to execute sections of code transactionally. This is done in conjunction with additionally created classes that hold information about the positions of fields within the original classes.
So far so good, and this all works fine with Scala 2.7 and 2.8, the problems arises with Scala 2.9. When trying to use this system under 2.9 the program fails with depending on which of my TM set-ups I'm using a field or a method not found exception. In both cases these are fields or methods that should have been added by the Java Agent. It would appear that the code that the JVM is seeing at this point has not been extended by the Java Agent. The addition of print statements confirms that the Java Agent is running for the classes required. The fact that the program is trying to access the fields that are only inserted by the Java Agent shows that at least some of the rewritten code is being executed. Examining the compiled Scala code shows no obvious changes for the files in question between 2.7 and 2.9. Running the Java Agent on the code outside of the runtime environment produces the correct rewritten code. All of these tests have been performed with the same JVM. Does anyone have any thoughts on what has changed between 2.8 and 2.9 that would cause this error? Is there some new verification of class signatures?
Many thanks in advance
Daniel
--
Martin Odersky
Prof., EPFL and Chairman, Typesafe
PSED, 1015 Lausanne, Switzerland
Tel. EPFL: +41 21 693 6863
Tel. Typesafe: +41 21 691 4967
Cheers
-- Martin
On Sat, Jul 9, 2011 at 12:28 PM, Daniel Goodman <goodmand@cs.man.ac.uk> wrote:
--
Martin Odersky
Prof., EPFL and Chairman, Typesafe
PSED, 1015 Lausanne, Switzerland
Tel. EPFL: +41 21 693 6863
Tel. Typesafe: +41 21 691 4967