I want to know the location that JVM allocates to objects being placed in the system memory.
-
20Ok, I'll ask: why?Oliver Charlesworth– Oliver Charlesworth2011-08-14 22:41:31 +00:00Commented Aug 14, 2011 at 22:41
-
2Possible duplicate of Memory address of variables in JavaCiro Santilli OurBigBook.com– Ciro Santilli OurBigBook.com2015-10-26 07:55:42 +00:00Commented Oct 26, 2015 at 7:55
-
3@CiroSantilli烏坎事件2016六四事件法轮功 No. That one is asking whether something is a memory address. This one is asking how to get the memory address.user207421– user2074212016-10-07 06:35:17 +00:00Commented Oct 7, 2016 at 6:35
4 Answers
This is something you probably don't want to do.
If you really want to do this, something like this code might help:
package test;
import java.lang.reflect.Field;
import sun.misc.Unsafe;
public class Addresser
{
private static Unsafe unsafe;
static
{
try
{
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (Unsafe)field.get(null);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static long addressOf(Object o)
throws Exception
{
Object[] array = new Object[] {o};
long baseOffset = unsafe.arrayBaseOffset(Object[].class);
int addressSize = unsafe.addressSize();
long objectAddress;
switch (addressSize)
{
case 4:
objectAddress = unsafe.getInt(array, baseOffset);
break;
case 8:
objectAddress = unsafe.getLong(array, baseOffset);
break;
default:
throw new Error("unsupported address size: " + addressSize);
}
return(objectAddress);
}
public static void main(String... args)
throws Exception
{
Object mine = "Hi there".toCharArray();
long address = addressOf(mine);
System.out.println("Addess: " + address);
//Verify address works - should see the characters in the array in the output
printBytes(address, 27);
}
public static void printBytes(long objectAddress, int num)
{
for (long i = 0; i < num; i++)
{
int cur = unsafe.getByte(objectAddress + i);
System.out.print((char)cur);
}
System.out.println();
}
}
But
- not portable across JVMs or even different versions
- objects can move because of GC at any time, and cannot synchronize across GCs so results might not make sense
- not tested across all architectures, endianess, etc. might make this not work everywhere
1 Comment
unsafe.addressSize() on 64-bit Sun JDKs returns 8 even when UseCompressedOpps is on. Using unsafe.arrayIndexScale(Object[].class), which returns 4 in that case, seems to be more likely to work with this technique (after all, you are storing the object in an Object array). With compressed oops, the address returned is not a true address - it may be shifted right by 3 bits, etc.Without using JVM-specific features this cannot be done. Java deliberately hides the location associated with each object to give the implementation more flexibility (the JVM often moves objects around in memory when doing garbage collection) and to improve security (you can't use raw pointers to trash memory or access nonexistent objects).
3 Comments
Object.hashCode()? It returns the memory address of the object, isn't it? Does it use the Unsafe class which @prunge told about? I know it is a native method, so maybe this is simply a pointer-to-int cast in C++?Object.hashCode() does not return the memory address of the object. It's implementation-specific. I spent several months working on a JavaScript implementation of a JVM where you can't work with raw addresses and implemented Object.hashCode() by just having a counter I incremented for each object. On some implementations this may be how Object.hashCode() works, but because many JVMs move objects around in memory you cannot rely on this being true.System.identityHashcode(Object) is significantly more complicated than returning the memory address of an object ... even if that is what it seems to do. For a start, it has to return the same value even if the GC has moved the object. This typically entails saving the value in the object. (Some JVM's do this in a clever way that minimizes the overhead ... but you do pay in the end.)You can use http://openjdk.java.net/projects/code-tools/jol to parse object layouts and get locations in memory. For one object you can use:
System.out.println(
GraphLayout.parseInstance(someObject).toPrintable());
System.out.println("Current address: " + VM.current().addressOf(someObject));
2 Comments
I want to know the location that JVM allocates to objects
You can't, because it doesn't exist. It changes over time due to garbage-collector action. There is no such thing as 'the location'.