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

Case objects equality problem

3 replies
toivo a
Joined: 2011-12-25,
User offline. Last seen 42 years 45 weeks ago.

sealed abstract class OfferingEvent
case object PhaseStarted extends OfferingEvent

val event = PhaseStarted

event equals PhaseStarted

and comparing event with PhaseStarted with equals method should always
return true
Is this correct?

It seems what Scala 2.9.1 case object does not generate equals method
(but case class generate equals method)

So comparing case objects relies using Object.equals method.
public boolean equals(Object obj) {
return (this == obj);
}

Usually this isn't a problem.
Simple Unit test run correctly always.

But under Tomcat 6 and OpenJDK 64-Bit Server VM (build 1.6.0-b09,
mixed mode)
equals sometimes fails.

To investigate problem I overridden equals method :

sealed abstract class OfferingEvent
{
val logger = Logger.getLogger("xxxxx")

override def equals(obj: Any): Boolean = {
val result = super.equals(obj)
logger.info("##-- this: " + this.getClass + " hashCode: " +
this.hashCode + " identityHashCode: " +
System.identityHashCode(this) )
logger.info("##-- obj: " + obj.getClass + " hashCode: " +
obj.hashCode + " identityHashCode: " + System.identityHashCode(obj) )
logger.info("##-- equals : " + result)

result
}
}

And result is :

Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
-50818394 identityHashCode: 4657709

Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
-50818394 identityHashCode: 1922540027

Dec 25, 2011 20:32:08 INFO ##-- equals : false

Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
-50818394 identityHashCode: 1059528513

Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
-50818394 identityHashCode: 1922540027

Dec 25, 2011 20:32:08 INFO ##-- equals : false

Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
-50818394 identityHashCode: 1922540027

Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
-50818394 identityHashCode: 1922540027

Dec 25, 2011 20:32:08 INFO ##-- equals : true

PhaseStarted hashCode is always same, and if equals is overridden like
in case class it should return correct result – true
But identityHashCode returns different reference id-s and it seems ==
uses identityHashCode-s.

I do not use reflection or any other tricky method to create
PhaseStarted objects.
Always simply

val event = PhaseStarted

But under Tomcat PhaseStarted are created at different times and maybe
for some reason new objects are created.
Note – I don't use different servlets either, all happens under same
servlet.

I am confused.

thanks for any help
toivo

H-star Development
Joined: 2010-04-14,
User offline. Last seen 2 years 26 weeks ago.
Re: Case objects equality problem

maybe the class is loaded by different classloaders? i heard rumors
about problems resulting from this

Am 25.12.2011 20:18, schrieb toivo a:
> sealed abstract class OfferingEvent
> case object PhaseStarted extends OfferingEvent
>
> val event = PhaseStarted
>
> event equals PhaseStarted
>
> and comparing event with PhaseStarted with equals method should always
> return true
> Is this correct?
>
> It seems what Scala 2.9.1 case object does not generate equals method
> (but case class generate equals method)
>
> So comparing case objects relies using Object.equals method.
> public boolean equals(Object obj) {
> return (this == obj);
> }
>
> Usually this isn't a problem.
> Simple Unit test run correctly always.
>
> But under Tomcat 6 and OpenJDK 64-Bit Server VM (build 1.6.0-b09,
> mixed mode)
> equals sometimes fails.
>
> To investigate problem I overridden equals method :
>
> sealed abstract class OfferingEvent
> {
> val logger = Logger.getLogger("xxxxx")
>
> override def equals(obj: Any): Boolean = {
> val result = super.equals(obj)
> logger.info("##-- this: " + this.getClass + " hashCode: " +
> this.hashCode + " identityHashCode: " +
> System.identityHashCode(this) )
> logger.info("##-- obj: " + obj.getClass + " hashCode: " +
> obj.hashCode + " identityHashCode: " + System.identityHashCode(obj) )
> logger.info("##-- equals : " + result)
>
> result
> }
> }
>
> And result is :
>
> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
> -50818394 identityHashCode: 4657709
>
> Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
> -50818394 identityHashCode: 1922540027
>
> Dec 25, 2011 20:32:08 INFO ##-- equals : false
>
>
> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
> -50818394 identityHashCode: 1059528513
>
> Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
> -50818394 identityHashCode: 1922540027
>
> Dec 25, 2011 20:32:08 INFO ##-- equals : false
>
>
> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
> -50818394 identityHashCode: 1922540027
>
> Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
> -50818394 identityHashCode: 1922540027
>
> Dec 25, 2011 20:32:08 INFO ##-- equals : true
>
>
> PhaseStarted hashCode is always same, and if equals is overridden like
> in case class it should return correct result – true
> But identityHashCode returns different reference id-s and it seems ==
> uses identityHashCode-s.
>
> I do not use reflection or any other tricky method to create
> PhaseStarted objects.
> Always simply
>
> val event = PhaseStarted
>
> But under Tomcat PhaseStarted are created at different times and maybe
> for some reason new objects are created.
> Note – I don't use different servlets either, all happens under same
> servlet.
>
> I am confused.
>
> thanks for any help
> toivo
>
>
>

H-star Development
Joined: 2010-04-14,
User offline. Last seen 2 years 26 weeks ago.
Re: Case objects equality problem

does it happen in local scope? or do you store a reference somewhere and
compare it to the object later? because a session might have gotten
serialized and deserialized again - no idea what that does to an object

Am 25.12.2011 21:14, schrieb HamsterofDeath:
> maybe the class is loaded by different classloaders? i heard rumors
> about problems resulting from this
>
> Am 25.12.2011 20:18, schrieb toivo a:
>> sealed abstract class OfferingEvent
>> case object PhaseStarted extends OfferingEvent
>>
>> val event = PhaseStarted
>>
>> event equals PhaseStarted
>>
>> and comparing event with PhaseStarted with equals method should always
>> return true
>> Is this correct?
>>
>> It seems what Scala 2.9.1 case object does not generate equals method
>> (but case class generate equals method)
>>
>> So comparing case objects relies using Object.equals method.
>> public boolean equals(Object obj) {
>> return (this == obj);
>> }
>>
>> Usually this isn't a problem.
>> Simple Unit test run correctly always.
>>
>> But under Tomcat 6 and OpenJDK 64-Bit Server VM (build 1.6.0-b09,
>> mixed mode)
>> equals sometimes fails.
>>
>> To investigate problem I overridden equals method :
>>
>> sealed abstract class OfferingEvent
>> {
>> val logger = Logger.getLogger("xxxxx")
>>
>> override def equals(obj: Any): Boolean = {
>> val result = super.equals(obj)
>> logger.info("##-- this: " + this.getClass + " hashCode: " +
>> this.hashCode + " identityHashCode: " +
>> System.identityHashCode(this) )
>> logger.info("##-- obj: " + obj.getClass + " hashCode: " +
>> obj.hashCode + " identityHashCode: " + System.identityHashCode(obj) )
>> logger.info("##-- equals : " + result)
>>
>> result
>> }
>> }
>>
>> And result is :
>>
>> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
>> -50818394 identityHashCode: 4657709
>>
>> Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
>> -50818394 identityHashCode: 1922540027
>>
>> Dec 25, 2011 20:32:08 INFO ##-- equals : false
>>
>>
>> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
>> -50818394 identityHashCode: 1059528513
>>
>> Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
>> -50818394 identityHashCode: 1922540027
>>
>> Dec 25, 2011 20:32:08 INFO ##-- equals : false
>>
>>
>> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
>> -50818394 identityHashCode: 1922540027
>>
>> Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
>> -50818394 identityHashCode: 1922540027
>>
>> Dec 25, 2011 20:32:08 INFO ##-- equals : true
>>
>>
>> PhaseStarted hashCode is always same, and if equals is overridden like
>> in case class it should return correct result – true
>> But identityHashCode returns different reference id-s and it seems ==
>> uses identityHashCode-s.
>>
>> I do not use reflection or any other tricky method to create
>> PhaseStarted objects.
>> Always simply
>>
>> val event = PhaseStarted
>>
>> But under Tomcat PhaseStarted are created at different times and maybe
>> for some reason new objects are created.
>> Note – I don't use different servlets either, all happens under same
>> servlet.
>>
>> I am confused.
>>
>> thanks for any help
>> toivo
>>
>>
>>
>

toivo a
Joined: 2011-12-25,
User offline. Last seen 42 years 45 weeks ago.
Re: Case objects equality problem

No, I don't store references in session and serialization is not used.

But I do use scala Actor.
And actor is singleton and holds events list.
val offerings = new ListBuffer[Offering]
actor listens outside messages and calls processing logic.
Processing logic examines events list and decides what do to next.
Events in list never get deleted or updated, only new events can be
appended.
Because actor process everything sequentially, I hope where is no race
conditions and synchronization is not needed.

Class loaders may be culprit.
But I don't nothing unusual. And it's hard to believe what Tomcat
changes classloaders during lifecycle of simple servlet.

On Dec 25, 10:30 pm, HamsterofDeath wrote:
> does it happen in local scope? or do you store a reference somewhere and
> compare it to the object later? because a session might have gotten
> serialized and deserialized again - no idea what that does to an object
>
> Am 25.12.2011 21:14, schrieb HamsterofDeath:
>
>
>
>
>
>
>
> > maybe the class is loaded by different classloaders? i heard rumors
> > about problems resulting from this
>
> > Am 25.12.2011 20:18, schrieb toivo a:
> >> sealed abstract class OfferingEvent
> >> case object PhaseStarted extends OfferingEvent
>
> >>   val event = PhaseStarted
>
> >>   event equals PhaseStarted
>
> >> and comparing event with PhaseStarted with equals method should always
> >> return true
> >> Is this correct?
>
> >> It seems what Scala 2.9.1 case object does not generate equals method
> >> (but case class generate equals method)
>
> >> So comparing case objects relies using Object.equals method.
> >>     public boolean equals(Object obj) {
> >>        return (this == obj);
> >>     }
>
> >> Usually this isn't a problem.
> >> Simple Unit test run correctly always.
>
> >> But under Tomcat 6 and OpenJDK 64-Bit Server VM (build 1.6.0-b09,
> >> mixed mode)
> >> equals sometimes fails.
>
> >> To investigate problem I overridden equals method :
>
> >> sealed abstract class OfferingEvent
> >> {
> >>   val logger = Logger.getLogger("xxxxx")
>
> >>   override def equals(obj: Any): Boolean = {
> >>     val result = super.equals(obj)
> >>     logger.info("##-- this: " + this.getClass + " hashCode: " +
> >> this.hashCode + " identityHashCode: " +
> >> System.identityHashCode(this) )
> >>     logger.info("##-- obj:  " + obj.getClass  + " hashCode: " +
> >> obj.hashCode  + " identityHashCode: " + System.identityHashCode(obj) )
> >>     logger.info("##-- equals : " + result)
>
> >>     result
> >>   }
> >> }
>
> >> And result is :
>
> >> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
> >> -50818394 identityHashCode: 4657709
>
> >> Dec 25, 2011 20:32:08 INFO ##-- obj:  class jd.PhaseStarted$ hashCode:
> >> -50818394 identityHashCode: 1922540027
>
> >> Dec 25, 2011 20:32:08 INFO ##-- equals : false
>
> >> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
> >> -50818394 identityHashCode: 1059528513
>
> >> Dec 25, 2011 20:32:08 INFO ##-- obj:  class jd.PhaseStarted$ hashCode:
> >> -50818394 identityHashCode: 1922540027
>
> >> Dec 25, 2011 20:32:08 INFO ##-- equals : false
>
> >> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
> >> -50818394 identityHashCode: 1922540027
>
> >> Dec 25, 2011 20:32:08 INFO ##-- obj:  class jd.PhaseStarted$ hashCode:
> >> -50818394 identityHashCode: 1922540027
>
> >> Dec 25, 2011 20:32:08 INFO ##-- equals : true
>
> >> PhaseStarted hashCode is always same, and if equals is overridden like
> >> in case class it should return correct result true
> >> But identityHashCode returns different reference id-s and it seems ==
> >> uses  identityHashCode-s.
>
> >> I do not use reflection or any other tricky method to create
> >> PhaseStarted objects.
> >> Always simply
>
> >>    val event = PhaseStarted
>
> >> But under Tomcat PhaseStarted are created at different times and maybe
> >> for some reason new objects are created.
> >> Note I don't use different servlets either, all happens under same
> >> servlet.
>
> >> I am confused.
>
> >> thanks for any help
> >> toivo

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