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

Inner objects inside a class are not singletons

7 replies
Sebastien Bocq
Joined: 2008-12-18,
User offline. Last seen 42 years 45 weeks ago.
Hi,

I always thoutht the scala 'object' keyword is used to declare a "singleton object" but this thruth doesn't seem to hold for inner objects inside a 'class'. Let me explain using the sample class below and the ouptut generated by javap.

--- Scala ---

abstract class MyType

class InnerObjectTest {
  object unique extends MyType
}

--- javap ---

private InnerObjectTest$unique$ unique$module;
...
public final InnerObjectTest$unique$ unique();
  Code:
   0:   aload_0
   1:   getfield        #18; //Field unique$module:LInnerObjectTest$unique$;
   4:   ifnonnull       19
   7:   aload_0
   8:   new     #20; //class InnerObjectTest$unique$
   11:  dup
   12:  aload_0
   13:  invokespecial   #23; //Method InnerObjectTest$unique$."<init>":(LInnerObjectTest;)V
   16:  putfield        #18; //Field unique$module:LInnerObjectTest$unique$;
   19:  aload_0
   20:  getfield        #18; //Field unique$module:LInnerObjectTest$unique$;
   23:  areturn
 

If I understand correctly the bytecode above, the compiler generates a unique() method to initialize a private field named "unique$module" to a reference to a new instance of type "InnerObjectTest$unique$".

If several threads access the 'unique' "singleton" concurrently, isn't there a small chance that they get different objects? In this is true, then I find this confusing because when obtaining a reference to a singleton instance one doesn't expect to worry about multi-threading issues.

Thanks,
Sebastien
sht
Joined: 2008-08-20,
User offline. Last seen 4 years 9 weeks ago.
Re: Inner objects inside a class are not singletons

fre, 19 12 2008 kl. 12:06 +0100, skrev Sebastien Bocq:
> Hi,
>
> I always thoutht the scala 'object' keyword is used to declare a
> "singleton object" but this thruth doesn't seem to hold for inner
> objects inside a 'class'. Let me explain using the sample class below
> and the ouptut generated by javap.
>
Each instance of InnerObjectTest get their own object. It is related to
path dependent types in Scala.

Szymon Jachim
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Inner objects inside a class are not singletons
Singleton as defined by most people mean "single instance per application" (what the heck is "application" anyways?).

Scalas definition is single instance per scope in which it's defined.
Gives more flexibility and causes less problems then typical statics.

In my team there's a joke: "it's not a global variable, it's a singleton!"

Szymon

On Fri, Dec 19, 2008 at 12:06 PM, Sebastien Bocq <sebastien.bocq@gmail.com> wrote:
Hi,

I always thoutht the scala 'object' keyword is used to declare a "singleton object" but this thruth doesn't seem to hold for inner objects inside a 'class'. Let me explain using the sample class below and the ouptut generated by javap.

--- Scala ---

abstract class MyType

class InnerObjectTest {
  object unique extends MyType
}

--- javap ---

private InnerObjectTest$unique$ unique$module;
...
public final InnerObjectTest$unique$ unique();
  Code:
   0:   aload_0
   1:   getfield        #18; //Field unique$module:LInnerObjectTest$unique$;
   4:   ifnonnull       19
   7:   aload_0
   8:   new     #20; //class InnerObjectTest$unique$
   11:  dup
   12:  aload_0
   13:  invokespecial   #23; //Method InnerObjectTest$unique$."<init>":(LInnerObjectTest;)V
   16:  putfield        #18; //Field unique$module:LInnerObjectTest$unique$;
   19:  aload_0
   20:  getfield        #18; //Field unique$module:LInnerObjectTest$unique$;
   23:  areturn
 

If I understand correctly the bytecode above, the compiler generates a unique() method to initialize a private field named "unique$module" to a reference to a new instance of type "InnerObjectTest$unique$".

If several threads access the 'unique' "singleton" concurrently, isn't there a small chance that they get different objects? In this is true, then I find this confusing because when obtaining a reference to a singleton instance one doesn't expect to worry about multi-threading issues.

Thanks,
Sebastien

Szymon Jachim
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Inner objects inside a class are not singletons
Yes. But Sebastien is right about multithreading problem.

It two threads reference an object at once (and both try to initialize it) it might happen that one calls

>    1:   getfield        #18; //Field unique$module:LInnerObjectTest

before the other does

>    16:  putfield        #18; //Field unique$module:LInnerObjectTest

and effectively there will be two instances of the object.

But don't have much experiance on JVM programming so I might be talking non-sense.

Szymon

On Fri, Dec 19, 2008 at 12:24 PM, Simon Holm Thøgersen <odie@cs.aau.dk> wrote:
fre, 19 12 2008 kl. 12:06 +0100, skrev Sebastien Bocq:
> Hi,
>
> I always thoutht the scala 'object' keyword is used to declare a
> "singleton object" but this thruth doesn't seem to hold for inner
> objects inside a 'class'. Let me explain using the sample class below
> and the ouptut generated by javap.
>
Each instance of InnerObjectTest get their own object. It is related to
path dependent types in Scala.

> --- Scala ---
>
> abstract class MyType
>
> class InnerObjectTest {
>   object unique extends MyType
> }
>
> --- javap ---
>
> private InnerObjectTest$unique$ unique$module;
> ...
> public final InnerObjectTest$unique$ unique();
>   Code:
>    0:   aload_0
>    1:   getfield        #18; //Field unique$module:LInnerObjectTest
> $unique$;
>    4:   ifnonnull       19
>    7:   aload_0
>    8:   new     #20; //class InnerObjectTest$unique$
>    11:  dup
>    12:  aload_0
>    13:  invokespecial   #23; //Method InnerObjectTest$unique
> $."<init>":(LInnerObjectTest;)V
>    16:  putfield        #18; //Field unique$module:LInnerObjectTest
> $unique$;
>    19:  aload_0
>    20:  getfield        #18; //Field unique$module:LInnerObjectTest
> $unique$;
>    23:  areturn
>
>
> If I understand correctly the bytecode above, the compiler generates a
> unique() method to initialize a private field named "unique$module" to
> a reference to a new instance of type "InnerObjectTest$unique$".

So you see exactly what I describe above, right?

> If several threads access the 'unique' "singleton" concurrently, isn't
> there a small chance that they get different objects? In this is true,
> then I find this confusing because when obtaining a reference to a
> singleton instance one doesn't expect to worry about multi-threading
> issues.


Simon Holm Thøgersen


Szymon Jachim
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Inner objects inside a class are not singletons
But you might be right about multithreading problem...
I think it should be synchronized, but I guess simple solution could be very costly?

Szymon

On Fri, Dec 19, 2008 at 12:15 PM, Szymon Jachim <sjachim@gmail.com> wrote:
Singleton as defined by most people mean "single instance per application" (what the heck is "application" anyways?).

Scalas definition is single instance per scope in which it's defined.
Gives more flexibility and causes less problems then typical statics.

In my team there's a joke: "it's not a global variable, it's a singleton!"

Szymon


On Fri, Dec 19, 2008 at 12:06 PM, Sebastien Bocq <sebastien.bocq@gmail.com> wrote:
Hi,

I always thoutht the scala 'object' keyword is used to declare a "singleton object" but this thruth doesn't seem to hold for inner objects inside a 'class'. Let me explain using the sample class below and the ouptut generated by javap.

--- Scala ---

abstract class MyType

class InnerObjectTest {
  object unique extends MyType
}

--- javap ---

private InnerObjectTest$unique$ unique$module;
...
public final InnerObjectTest$unique$ unique();
  Code:
   0:   aload_0
   1:   getfield        #18; //Field unique$module:LInnerObjectTest$unique$;
   4:   ifnonnull       19
   7:   aload_0
   8:   new     #20; //class InnerObjectTest$unique$
   11:  dup
   12:  aload_0
   13:  invokespecial   #23; //Method InnerObjectTest$unique$."<init>":(LInnerObjectTest;)V
   16:  putfield        #18; //Field unique$module:LInnerObjectTest$unique$;
   19:  aload_0
   20:  getfield        #18; //Field unique$module:LInnerObjectTest$unique$;
   23:  areturn
 

If I understand correctly the bytecode above, the compiler generates a unique() method to initialize a private field named "unique$module" to a reference to a new instance of type "InnerObjectTest$unique$".

If several threads access the 'unique' "singleton" concurrently, isn't there a small chance that they get different objects? In this is true, then I find this confusing because when obtaining a reference to a singleton instance one doesn't expect to worry about multi-threading issues.

Thanks,
Sebastien


Lauri Alanko
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Inner objects inside a class are not singletons

On Fri, Dec 19, 2008 at 12:23:34PM +0100, Szymon Jachim wrote:
> But you might be right about multithreading problem...
> I think it should be synchronized, but I guess simple solution could be very
> costly?

Synchronization is probably not _too_ costly in this context, but it
can be avoided with modern JVMs:

http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#dcl

Lauri

David Pollak
Joined: 2008-12-16,
User offline. Last seen 42 years 45 weeks ago.
Re: Inner objects inside a class are not singletons
Yeah, object access/initialization code should be the same as lazy val access/initialization code.  This looks like a bug to me.  I'd suggest you file it.

On Fri, Dec 19, 2008 at 3:29 AM, Szymon Jachim <sjachim@gmail.com> wrote:
Yes. But Sebastien is right about multithreading problem.

It two threads reference an object at once (and both try to initialize it) it might happen that one calls


>    1:   getfield        #18; //Field unique$module:LInnerObjectTest

before the other does

>    16:  putfield        #18; //Field unique$module:LInnerObjectTest

and effectively there will be two instances of the object.

But don't have much experiance on JVM programming so I might be talking non-sense.

Szymon


On Fri, Dec 19, 2008 at 12:24 PM, Simon Holm Thøgersen <odie@cs.aau.dk> wrote:
fre, 19 12 2008 kl. 12:06 +0100, skrev Sebastien Bocq:
> Hi,
>
> I always thoutht the scala 'object' keyword is used to declare a
> "singleton object" but this thruth doesn't seem to hold for inner
> objects inside a 'class'. Let me explain using the sample class below
> and the ouptut generated by javap.
>
Each instance of InnerObjectTest get their own object. It is related to
path dependent types in Scala.

> --- Scala ---
>
> abstract class MyType
>
> class InnerObjectTest {
>   object unique extends MyType
> }
>
> --- javap ---
>
> private InnerObjectTest$unique$ unique$module;
> ...
> public final InnerObjectTest$unique$ unique();
>   Code:
>    0:   aload_0
>    1:   getfield        #18; //Field unique$module:LInnerObjectTest
> $unique$;
>    4:   ifnonnull       19
>    7:   aload_0
>    8:   new     #20; //class InnerObjectTest$unique$
>    11:  dup
>    12:  aload_0
>    13:  invokespecial   #23; //Method InnerObjectTest$unique
> $."<init>":(LInnerObjectTest;)V
>    16:  putfield        #18; //Field unique$module:LInnerObjectTest
> $unique$;
>    19:  aload_0
>    20:  getfield        #18; //Field unique$module:LInnerObjectTest
> $unique$;
>    23:  areturn
>
>
> If I understand correctly the bytecode above, the compiler generates a
> unique() method to initialize a private field named "unique$module" to
> a reference to a new instance of type "InnerObjectTest$unique$".

So you see exactly what I describe above, right?

> If several threads access the 'unique' "singleton" concurrently, isn't
> there a small chance that they get different objects? In this is true,
> then I find this confusing because when obtaining a reference to a
> singleton instance one doesn't expect to worry about multi-threading
> issues.


Simon Holm Thøgersen





--
Lift, the simply functional web framework http://liftweb.net
Collaborative Task Management http://much4.us
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp
Sebastien Bocq
Joined: 2008-12-18,
User offline. Last seen 42 years 45 weeks ago.
Re: Inner objects inside a class are not singletons
Done.

https://lampsvn.epfl.ch/trac/scala/ticket/1591

2008/12/19 David Pollak <feeder.of.the.bears@gmail.com>
Yeah, object access/initialization code should be the same as lazy val access/initialization code.  This looks like a bug to me.  I'd suggest you file it.


On Fri, Dec 19, 2008 at 3:29 AM, Szymon Jachim <sjachim@gmail.com> wrote:
Yes. But Sebastien is right about multithreading problem.

It two threads reference an object at once (and both try to initialize it) it might happen that one calls


>    1:   getfield        #18; //Field unique$module:LInnerObjectTest

before the other does

>    16:  putfield        #18; //Field unique$module:LInnerObjectTest

and effectively there will be two instances of the object.

But don't have much experiance on JVM programming so I might be talking non-sense.

Szymon


On Fri, Dec 19, 2008 at 12:24 PM, Simon Holm Thøgersen <odie@cs.aau.dk> wrote:
fre, 19 12 2008 kl. 12:06 +0100, skrev Sebastien Bocq:
> Hi,
>
> I always thoutht the scala 'object' keyword is used to declare a
> "singleton object" but this thruth doesn't seem to hold for inner
> objects inside a 'class'. Let me explain using the sample class below
> and the ouptut generated by javap.
>
Each instance of InnerObjectTest get their own object. It is related to
path dependent types in Scala.

> --- Scala ---
>
> abstract class MyType
>
> class InnerObjectTest {
>   object unique extends MyType
> }
>
> --- javap ---
>
> private InnerObjectTest$unique$ unique$module;
> ...
> public final InnerObjectTest$unique$ unique();
>   Code:
>    0:   aload_0
>    1:   getfield        #18; //Field unique$module:LInnerObjectTest
> $unique$;
>    4:   ifnonnull       19
>    7:   aload_0
>    8:   new     #20; //class InnerObjectTest$unique$
>    11:  dup
>    12:  aload_0
>    13:  invokespecial   #23; //Method InnerObjectTest$unique
> $."<init>":(LInnerObjectTest;)V
>    16:  putfield        #18; //Field unique$module:LInnerObjectTest
> $unique$;
>    19:  aload_0
>    20:  getfield        #18; //Field unique$module:LInnerObjectTest
> $unique$;
>    23:  areturn
>
>
> If I understand correctly the bytecode above, the compiler generates a
> unique() method to initialize a private field named "unique$module" to
> a reference to a new instance of type "InnerObjectTest$unique$".

So you see exactly what I describe above, right?

> If several threads access the 'unique' "singleton" concurrently, isn't
> there a small chance that they get different objects? In this is true,
> then I find this confusing because when obtaining a reference to a
> singleton instance one doesn't expect to worry about multi-threading
> issues.


Simon Holm Thøgersen





--
Lift, the simply functional web framework http://liftweb.net
Collaborative Task Management http://much4.us
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp

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