Skip to content

Instantly share code, notes, and snippets.

@nitsanw
nitsanw / gist:8941371
Created February 11, 2014 18:46
Final field is loaded twice
# {method} 'poll' '()Ljava/lang/Object;' in 'io/jaq/spsc/FFBuffer' BEFORE
# [sp+0x20] (sp of caller)
0x00007facb1060c80: mov r10d,DWORD PTR [rsi+0x8]
0x00007facb1060c84: cmp rax,r10
0x00007facb1060c87: jne 0x00007facb1037960 ; {runtime_call}
0x00007facb1060c8d: xchg ax,ax
[Verified Entry Point]
0x00007facb1060c90: sub rsp,0x18
0x00007facb1060c97: mov QWORD PTR [rsp+0x10],rbp ;*synchronization entry
; - io.jaq.spsc.FFBuffer::poll@-1 (line 133)
@nitsanw
nitsanw / gist:8941532
Created February 11, 2014 18:55
FFBuffer.poll(): buffer localized
public E poll() {
final long offset = offset(head);
final E[] lb = buffer;
@SuppressWarnings("unchecked")
final E e = (E) UnsafeAccess.UNSAFE.getObjectVolatile(lb, offset);
if (null == e) {
return null;
}
UnsafeAccess.UNSAFE.putOrderedObject(lb, offset, null);
head++;
@nitsanw
nitsanw / gist:8941584
Created February 11, 2014 18:57
Final field localized
# {method} 'poll' '()Ljava/lang/Object;' in 'io/jaq/spsc/FFBuffer' AFTER
# [sp+0x20] (sp of caller)
0x00007f885ca2ccc0: mov r10d,DWORD PTR [rsi+0x8]
0x00007f885ca2ccc4: cmp rax,r10
0x00007f885ca2ccc7: jne 0x00007f885ca03960 ; {runtime_call}
0x00007f885ca2cccd: xchg ax,ax
[Verified Entry Point]
0x00007f885ca2ccd0: sub rsp,0x18
0x00007f885ca2ccd7: mov QWORD PTR [rsp+0x10],rbp ;*synchronization entry
; - io.jaq.spsc.FFBuffer::poll@-1 (line 133)
@nitsanw
nitsanw / gist:9135963
Created February 21, 2014 15:12
Unsafe address usage
/**
* Allocates a new block of native memory, of the given size in bytes.The
* contents of the memory are uninitialized; they will generally be
* garbage.The resulting native pointer will never be zero, and will be
* aligned for all value types.Dispose of this memory by calling {@link
* #freeMemory}, or resize it with {@link #reallocateMemory}.
*
* @throws IllegalArgumentException if the size is negative or too large
* for the native size_t type
*
@nitsanw
nitsanw / gist:9136084
Created February 21, 2014 15:20
The classic volatile read concurrency bug
class Foo{
volatile Foo next;
Foo getNextNext(){
// Commented out code as reminder of silly bug
// if (next != null) {
// // This can still result in NPE, next can change between reads
// return next.next;
// }
// This is how we do it!
@nitsanw
nitsanw / gist:9137081
Created February 21, 2014 16:10
Getting an Object address, from JOL
static final int REF_SIZE = ...;
static final int OBJECT_ARRAY_BASE = UNSAFE.arrayBaseOffset((Object[].class);
static final boolean USE_COMPRESSED_REFS = ...;
static final int COMPRESSED_REF_SHIFT = ...;
public static long addressOf(Object o) {
return addressOf(o, REF_SIZE);
}
public static long addressOf(Object o, int oopSize) {
Object[] array = new Object[1];
@nitsanw
nitsanw / gist:9137263
Created February 21, 2014 16:18
Use JOL utility to get object address
// Let Shipilev do all the heavy lifting!
import org.openjdk.jol.util.VMSupport;
...
// Suddenly, I feel the urge to get an object address
long address = VMSupport.addressOf(anUnsuspectingObject);
// Satisfied. I move on to never using that address...
...
@nitsanw
nitsanw / gist:9188712
Last active August 29, 2015 13:56
SizeOf object: Don't do this :(
public static long sizeOf(Object object) {
Unsafe unsafe = getUnsafe();
// Original : return unsafe.getAddress( normalize( unsafe.getInt(object, 4L) ) + 12L );
// This is my elaborate breakdown of original one liner
int addressOfKlassInObjectHeader = unsafe.getInt(object, 4L);
long nativeAddressOfKlass = normalize(addressOfKlassInObjectHeader);
long addressOfLayoutHelper = nativeAddressOfKlass + 12L;
return unsafe.getAddress(addressOfLayoutHelper);
}
@nitsanw
nitsanw / gist:9206588
Created February 25, 2014 10:35
Shallow copy, bad idea
static Object shallowCopy(Object obj) {
long size = sizeOf(obj);
long start = toAddress(obj);
long address = getUnsafe().allocateMemory(size);
getUnsafe().copyMemory(start, address, size);
return fromAddress(address);
}
static long toAddress(Object obj) {
Object[] array = new Object[] {obj};
@Override
public boolean offer(final E e) {
if (null == e) {
throw new NullPointerException("Null is not a valid element");
}
final long currHeadCache = lvHeadCache(); // Must load volatile, may have changed by other producer
long currentTail;
do {
currentTail = lvTail(); // Must load volatile, may have changed by other producer
final long wrapPoint = currentTail - capacity;