field names in generated bytecode

85 views
Skip to first unread message

Ant Kutschera

unread,
Aug 28, 2012, 5:13:17 PM8/28/12
to scala-l...@googlegroups.com
Hi,

I have the following Scala class:

    class SomeClass(var someInt: Int){}

The bytecode which is generated does me a favour because someInt is maintained as the field name.

Using javap, I can see that the method call someInt() is:

public int someInt();
...
  Code:
...
   1: getfield #13; //Field someInt:I

From the constants table, #13 is:

    const #13 = Field #2.#12; //  SomeClass.someInt:I

#2.#12 is:

    const #2 = class #1; //  SomeClass
    const #12 = NameAndType #9:#10;//  someInt:I

#1 is:

    const #1 = Asciz SomeClass;

#9 and #10 are:

    const #9 = Asciz someInt;
    const #10 = Asciz I;

#9 is the relevant part of all that.  It tells me that the name "someInt" is maintained in the bytecode.

Will this always be so, say with Scala 2.11 or 3.x?  In theory, I'm lead to believe that the generated bytecode could use "someOtherName" if it wanted, so long as the someInt() and someInt_$eq(int) methods were maintained.

The reason I ask is that if I use JPA, and I don't define the @Column(name='someInt') annotation, JPA will assume that the column in the database has the same name as the field.  But if at runtime, the field has an entirely different name, because Scala mangled the name when it generated the bytecode, I am screwed.

Thanks for feedback,
Ant

Simon Schäfer

unread,
Aug 28, 2012, 7:21:11 PM8/28/12
to scala-l...@googlegroups.com
You can never be sure if something stay forever because nobody knows
what future will bring us. Neverthelless I don't think there will be
occur so many cases which require a change of the current behavior. In
Scala currently it is impossible to directly generate private variables
without creating a Getter - the compiler enforces an access of the
Getter. Thus, there is no need to change the name of the variable
because no one is able to touch it.

Another point to mention is backwards compatibility. No one will change
existing behavior when it breaks huge code bases.

But who knows if one day we get a language feature which requires
direct access to the private variable of Scalas vals and vars...

On Tue 28 Aug 2012 11:13:17 PM CEST, Ant Kutschera wrote:
> Hi,
>
> I have the following Scala class:
>
> class SomeClass(var someInt: Int){}
>
> The bytecode which is generated does me a favour because someInt is
> maintained as the field name.
>
> Using javap, I can see that the method call someInt() is:
>
> public int someInt();
> ...
> Code:
> ...
> 1:getfield#13; //Field someInt:I
>
> From the constants table, #13 is:
>
> const #13 = Field#2.#12;// SomeClass.someInt:I
>
> #2.#12 is:
>
> const #2 = class#1;// SomeClass
> const #12 = NameAndType#9:#10;// someInt:I

Paolo Giarrusso

unread,
Sep 1, 2012, 2:06:10 PM9/1/12
to scala-l...@googlegroups.com
Il giorno martedì 28 agosto 2012 23:13:17 UTC+2, Ant Kutschera ha scritto:
Hi,

I have the following Scala class:

    class SomeClass(var someInt: Int){}

The bytecode which is generated does me a favour because someInt is maintained as the field name.
 
Will this always be so, say with Scala 2.11 or 3.x?  In theory, I'm lead to believe that the generated bytecode could use "someOtherName" if it wanted, so long as the someInt() and someInt_$eq(int) methods were maintained.

First, as said, changes there seem rather unlikely, but there's *in general* no guarantee, especially for 3.x, unless you get Scala core developers to document some sort of guarantee on what is part of the API and what not.
The last public discussion on Scala 3.x (by Martin Odersky) implied that not even source compatibility is not completely guaranteed between 2.x and 3.x, especially for some language features (https://groups.google.com/d/msg/scala-language/PV4q6O1qIh8/yG4p8PA2Jf8J), although Martin Odersky knows that existing code must be supported somehow.

The general attitude is to ease interoperability with Java, I would say*, so you can rely on anything which affects interoperability with Java in a significant way - if you can make your case, you can argue that any such change is a bug and get it accepted.
For instance, since Java reflection allows access to private fields, not only JPA but other Java code might rely on that.
More importantly, I suspect that serialization might give you a much stronger guarantee. Private fields are serialized, and changing their names (I believe) means that a serialized class cannot be serialized back (without writing custom deserialization code). If that's the case, the easiest way to not break serialization is to keep field names unchanged.

* This attitude was strong enough that now you can create real static methods with @static, simply because some Java libraries expect to call those (I've hit this with JUnit).

The reason I ask is that if I use JPA, and I don't define the @Column(name='someInt') annotation, JPA will assume that the column in the database has the same name as the field.  But if at runtime, the field has an entirely different name, because Scala mangled the name when it generated the bytecode, I am screwed.
But in the worst case, it sounds like you could still use the annotation, couldn't you? Or is that a massive change which can't be automated with search&replace with regexps?
If you wonder about source compatibility, you don't have that anyway. If your source compiles under 2.9, it might use some method which gets deprecated in 2.10 and removed in 2.11. The changes between 2.x and 3.x could be much more invasive, since they could affect some language features.
To sum up, what level of compatibility do you expect or need?

Cheers,
Paolo
Reply all
Reply to author
Forward
0 new messages