Created
March 25, 2020 10:56
-
-
Save shipilev/0ba1490d64c14645ee903fc695e931b5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.reflect.AccessibleObject; | |
import java.lang.reflect.Field; | |
public class Play { | |
public static void main(String[] args) throws Exception { | |
AddressExtractor ae = new AddressExtractor(); | |
Field pvField = AddressExtractor.class.getDeclaredField("pointerValue"); | |
Field type = Field.class.getDeclaredField("type"); | |
type.setAccessible(true); | |
type.set(pvField, Object.class); | |
// Setting is relatively safe: | |
Dummy dummy = new Dummy(); | |
pvField.set(ae, dummy); | |
System.out.println(Long.toHexString(ae.pointerValue)); | |
// Getting is NOT! | |
ae.pointerValue = 0xDEADBEEF; | |
// Used to be this in example: | |
//System.out.println(pvField.get(ae) == foo); | |
// It is the same as getting Object in the local. | |
// ...and if GC happens in the middle: | |
Object o = pvField.get(ae); | |
System.gc(); // SEGV, because "o" is not actually the object | |
System.out.println(o == dummy); | |
System.in.read(); | |
} | |
} | |
class AddressExtractor { | |
public long pointerValue; | |
} | |
class Dummy { | |
public long value; | |
} | |
/* | |
$ ~/Install/jdk8u232/bin/java Play | |
b002c00c | |
# | |
# A fatal error has been detected by the Java Runtime Environment: | |
# | |
# SIGSEGV (0xb) at pc=0x00007f85878c563c, pid=3437, tid=0x00007f85854af700 | |
# | |
# JRE version: OpenJDK Runtime Environment (8.0) (build 1.8.0-builds.shipilev.net-openjdk-jdk8-b24-20191015-jdk8u232-b09:jdk8u232-ga) | |
# Java VM: OpenJDK 64-Bit Server VM (25.71-b24-20191015-jdk8u232-09:jdk8u232-ga mixed mode linux-amd64 compressed oops) | |
# Problematic frame: | |
# V [libjvm.so+0x91363c] PSRootsClosure<false>::do_oop(oopDesc**)+0x1c | |
# | |
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again | |
# | |
# An error report file with more information is saved as: | |
# /home/shade/temp/reflect/hs_err_pid3437.log | |
# | |
# If you would like to submit a bug report, please visit: | |
# http://bugreport.java.com/bugreport/crash.jsp | |
# | |
Aborted (core dumped) | |
$ ~/Install/jdk11.0.6-ea/bin/java Play | |
WARNING: An illegal reflective access operation has occurred | |
WARNING: Illegal reflective access by Play (file:/home/shade/temp/reflect/) to field java.lang.reflect.Field.type | |
WARNING: Please consider reporting this to the maintainers of Play | |
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations | |
WARNING: All illegal access operations will be denied in a future release | |
Exception in thread "main" java.lang.IllegalArgumentException: Can not set long field AddressExtractor.pointerValue to Dummy | |
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167) | |
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171) | |
at java.base/jdk.internal.reflect.UnsafeLongFieldAccessorImpl.set(UnsafeLongFieldAccessorImpl.java:102) | |
at java.base/java.lang.reflect.Field.set(Field.java:780) | |
at Play.main(Play.java:14) | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment