• Bug
  • Status: Closed
  • 2 Major
  • Resolution: Fixed
  • Byte Code Transform
  • cdennis
  • Reporter: cdennis
  • October 12, 2009
  • 0
  • Watchers: 2
  • February 12, 2010
  • November 18, 2009


The getter TC generates for a final field currently looks something like this (simplified):

public Object getField() { synchronized (__tc_managed()) { if (field == null) { resolveReference(“fieldName”); } } return field }

For a final field I think this can be changed to something like this:

public Object getField() { if (field == null) { synchronized (__tc_managed()) { resolveReference(“fieldName”); } } return field }

The field is final - so if you see a non null value then it must be the correct one.

This has been seen to be a bottleneck in some of our performance tests…

PerAppThread-8” prio=10 tid=0x81c5c800 nid=0x69ca waiting for monitor entry [0x7df5c000] java.lang.Thread.State: BLOCKED (on object monitor) at org.terracotta.cache.serialization.ObjectStreamClassSerializer.__tc_getmappings(ObjectStreamClassSerializer.java) - waiting to lock <0x8a098750> (a com.tc.object.ObjectID) at org.terracotta.cache.serialization.ObjectStreamClassSerializer.getMappingFor(ObjectStreamClassSerializer.java:29) at org.terracotta.cache.serialization.DsoSerializationStrategy$OOS.writeClassDescriptor(DsoSerializationStrategy.java:85) at java.io.ObjectOutputStream.writeNonProxyDesc(ObjectOutputStream.java:1245) at java.io.ObjectOutputStream.writeClassDesc(ObjectOutputStream.java:1203) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1387) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326) at org.terracotta.cache.serialization.DsoSerializationStrategy.writeStringKey(DsoSerializationStrategy.java:54) at org.terracotta.cache.serialization.DsoSerializationStrategy.generateStringKeyFor(DsoSerializationStrategy.java:46) at org.terracotta.modules.ehcache.store.ClusteredStore.generateStringKeyFor(ClusteredStore.java:236) at org.terracotta.modules.ehcache.store.ClusteredStore.get(ClusteredStore.java:113)


Geert Bevin 2009-10-13

Looks like a correct and nice optimization to me!

Tim Eck 2009-10-13

I hesitate to even add this comment, but you can use reflection to modify final fields so that is one [very small] wrinkle. Perhaps when we add this there should be a tc.property to disable it in the off chance that someone needs mutable final fields in clustered objects. Another reason to add the property is if we discover some other bug later on :-)

Chris Dennis 2009-11-16

A couple of questions:

1) Assuming I connect this to a tc-property - what should that property be? 2) Should this be enabled or disabled when we create the boot-jar?

Tim Eck 2009-11-16

I don’t really care too much about the tc.property name (something like finalField.fastRead=true?).

boot jar time is a good question. I guess this behavior will be baked in the bytecode for those types. I guess since you can set tc properties in tc-config (and via a tc.properties in your lib dir) that I would do whatever TCProperties is telling you to do at that time. I guess we could write something in the boot jar meta data with the setting used then and refuse to run if the setting isn’t still the same when the L1 runs.

Even with reflection now that I think about it things might work okay. The node where the mutation occurs should be okay and the broadcast will null the field on apply. I’m still in favor of a switch though so we cover our butts if there is a bug and as a way to eliminate this as a cause whenever any other mysterious bugs are reported to us.

Chris Dennis 2009-11-18

I’ve added the instrumentation for this - it’s controlled by the “instrumentation.finalField.fastRead” property (which defaults to true).