2
private static final long SEGSHIFT_OFFSET;
SEGSHIFT_OFFSET = UNSAFE.objectFieldOffset(
            ConcurrentHashMap.class.getDeclaredField("segmentShift"));
UNSAFE.putIntVolatile(this, SEGSHIFT_OFFSET, 32);

the code adove can be replaced code as follows?

private static volatile long SEGSHIFT_OFFSET = 0L; 
SEGSHIFT_OFFSET = 32;

or can be replaced as follows?

private static synchronized long SEFSHIFT_OFFSET = 0L;
SEGSHIFT_OFFSET = 32;
Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
LiangbinHu
  • 51
  • 2

1 Answers1

1

I assume this code you have in some class which subclasses the ConcurrentHashMap class.

No, it cannot be replaced as you suggest. This code does very dangerous thing: it updates the package-private final field segmentShift of ConcurrentHashMap with the new value. SEGSHIFT_OFFSET is used to determine the offset of the segmentShift field within the class (number of bytes between this field location and the beginning of the object) in the memory. As this offset assumed to be the constant during JVM lifecycle, it's stored in the final field.

Your suggested replacements do completely different thing: just declare the field and change its value. This way you cannot change the value of inaccessible final segmentShift field. It's updated using the volatile semantic to put memory barrier after update, so other threads will see the updated value (though I still doubt whether it's a robust way to do this).

If you want to replace this code, you can try to use reflection, though this would not impose volatile semantics which is probably necessary in this case.

Note that this unsafe code will not work completely in JDK8, as the internal structure of ConcurrentHashMap is changed significantly and it has no segmentShift field anymore. If you want to upgrade to JDK8, then reflection will not help you either.

By the way there's an ongoing discussion about removing the Unsafe completely.

Community
  • 1
  • 1
Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334