This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Change of behaviour between Scala2.[7-8] and 2.9 when using Java Agents

5 replies
Daniel Goodman
Joined: 2010-06-22,
User offline. Last seen 42 years 45 weeks ago.

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

odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: Change of behaviour between Scala2.[7-8] and 2.9 when using
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@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

Daniel Goodman
Joined: 2010-06-22,
User offline. Last seen 42 years 45 weeks ago.
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:
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


Daniel Goodman
Joined: 2010-06-22,
User offline. Last seen 42 years 45 weeks ago.
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:dC2 BA -6-7b\nTWm;\t e9A\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:dC2 BA -6-7b\nTWm;\t e9A\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



Daniel Goodman
Joined: 2010-06-22,
User offline. Last seen 42 years 45 weeks ago.
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:
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:dC2 BA -6-7b\nTWm;\t e9A\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:dC2 BA -6-7b\nTWm;\t e9A\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




Daniel Goodman
Joined: 2010-06-22,
User offline. Last seen 42 years 45 weeks ago.
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:
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:dC2 BA -6-7b\nTWm;\t e9A\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:dC2 BA -6-7b\nTWm;\t e9A\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





Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland