Skip to content

Instantly share code, notes, and snippets.

@qudongfang
Last active February 12, 2024 14:36
  • Star 4 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save qudongfang/49635d86882c03e49cff2b0f7d833805 to your computer and use it in GitHub Desktop.
import sun.misc.Unsafe;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class Foo {
private boolean flag = true;
public boolean getFlag() {
return this.flag;
}
public static void main(String[] args) throws InvocationTargetException,
NoSuchMethodException,
InstantiationException,
IllegalAccessException,
NoSuchFieldException {
Foo foo = new Foo();
Field field = foo.getClass().getDeclaredField("flag");
Unsafe unsafe = foo.getUnsafeByConstructor();
long addr = unsafe.objectFieldOffset(field);
for (byte b = 0; b < 4; b++) {
System.out.println("Unsafe.putByte: " + b);
unsafe.putByte(foo, addr, b);
System.out.println("Unsafe.getByte: " + unsafe.getByte(foo, addr)); // 总是会打印出put的值
System.out.println("Unsafe.getBoolean: " + unsafe.getBoolean(foo, addr)); // 打印出的值,像是ifeq, flag != 0即true
System.out.println("foo.flag: " + foo.flag); // 像是ifeq, flag != 0即true
System.out.println("foo.getFlag: " + foo.getFlag()); // 像是 ((flag) & 1)
// 此处是内联了?
if (foo.flag) {
System.out.println("Hello, Java!" + " foo.flag");
}
// 此处是内联了?
if (true == foo.flag) {
System.out.println("Hello, JVM!" + " foo.flag");
}
if (foo.getFlag()) {
System.out.println("Hello, Java!" + " getFlag");
}
if (true == foo.getFlag()) {
System.out.println("Hello, JVM!" + " getFlag");
}
System.out.println("-----------------------------------------------------------");
}
}
private static Unsafe getUnsafeByConstructor() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Constructor<Unsafe> unsafeConstructor = Unsafe.class.getDeclaredConstructor();
unsafeConstructor.setAccessible(true);
Unsafe unsafe = unsafeConstructor.newInstance();
return unsafe;
}
private static Unsafe getUnsafe() throws NoSuchFieldException, IllegalAccessException {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafe.get(null);
return unsafe;
}
}
/*
unsafe.putByte(foo, addr, (byte)2); // 设置为: 2
System.out.println(unsafe.getByte(foo, addr)); // 打印getByte: 2
System.out.println(unsafe.getBoolean(foo, addr)); // 打印getBoolean: true
unsafe.putByte(foo, addr, (byte)1); // 设置为: 1
System.out.println(unsafe.getByte(foo, addr)); // 打印getByte: 1
System.out.println(unsafe.getBoolean(foo, addr)); // 打印getBoolean: true
------------------------------------------------------------------------------------
疑问:
if(foo.flag)判断,使用getfield Field flag:"Z",执行逻辑等于:0 != flag
if(foo.getFlag())判断,使用invokevirtual Method getFlag:"()Z",执行逻辑等于: 0 != ((flag) & 1)
求大神帮忙解答
*/
@DQinYuan
Copy link

你的程序在我的电脑上的输出如下:

Unsafe.putByte: 0
Unsafe.getByte: 0
Unsafe.getBoolean: false
foo.flag: false
foo.getFlag: false
-----------------------------------------------------------
Unsafe.putByte: 1
Unsafe.getByte: 1
Unsafe.getBoolean: true
foo.flag: true
foo.getFlag: true
Hello, Java! foo.flag
Hello, JVM! foo.flag
Hello, Java! getFlag
Hello, JVM! getFlag
-----------------------------------------------------------
Unsafe.putByte: 2
Unsafe.getByte: 2
Unsafe.getBoolean: true
foo.flag: true
foo.getFlag: true
Hello, Java! foo.flag
Hello, Java! getFlag
-----------------------------------------------------------
Unsafe.putByte: 3
Unsafe.getByte: 3
Unsafe.getBoolean: true
foo.flag: true
foo.getFlag: true
Hello, Java! foo.flag
Hello, Java! getFlag
-----------------------------------------------------------

感觉我无法复现你的现象,这是什么原因呢?

@DQinYuan
Copy link

换了台电脑就可以复现你们的结果了,我猜测会不会是因为有的硬件不支持单位的掩码?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment