fork download
  1. import java.io.ByteArrayOutputStream;
  2. import java.io.DataOutputStream;
  3. import java.io.IOException;
  4. import java.io.UncheckedIOException;
  5. import java.lang.invoke.MethodHandles;
  6. import java.lang.invoke.MethodType;
  7. import java.lang.reflect.Field;
  8. import java.nio.ByteBuffer;
  9. import java.util.Arrays;
  10. import java.util.function.ToIntFunction;
  11.  
  12. class Generator {
  13. public static void main(String[] args) throws Throwable {
  14. ToIntFunction<Thread> ft=generateIntFieldAccessor(Thread.class, "threadStatus");
  15. System.out.println(ft.applyAsInt(Thread.currentThread()));
  16. }
  17.  
  18. private static <X> ToIntFunction<X> generateIntFieldAccessor(
  19. Class<? super X> c, String name) throws Throwable {
  20.  
  21. byte[] code = Generator.generateIntReaderCode(c.getDeclaredField(name));
  22. Class<?> unsafe = Class.forName("sun.misc.Unsafe");
  23. Field u = unsafe.getDeclaredField("theUnsafe");
  24. u.setAccessible(true);
  25. Object theUnsafe = u.get(null);
  26. Class<ToIntFunction<X>> gen = (Class<ToIntFunction<X>>)
  27. MethodHandles.publicLookup().bind(theUnsafe, "defineAnonymousClass",
  28. MethodType.methodType(
  29. Class.class, Class.class, byte[].class, Object[].class))
  30. .invokeExact(c, code, (Object[])null);
  31. return gen.getConstructor().newInstance();
  32. }
  33.  
  34. private static final String HEAD = "Êþº¾\0\0\0004\0\24\7\0\21\7\0\t\7\0\n\7\0\22"
  35. + "\n\0\2\0\6\f\0\13\0\f\t\0\4\0\b\f\0\23\0\20\1\0\20java/lang/Object\1\0\40"
  36. + "java/util/function/ToIntFunction\1\0\6<init>\1\0\3()V\1\0\4Code\1\0\n"
  37. + "applyAsInt\1\0\25(Ljava/lang/Object;)I\1\0\1I";
  38. private static final String TAIL = "\0001\0\1\0\2\0\1\0\3\0\0\0\2\0\1\0\13\0\f\0"
  39. + "\1\0\r\0\0\0\21\0\1\0\1\0\0\0\5\0\5±\0\0\0\0\0\21\0\16\0\17\0\1\0\r\0\0"
  40. + "\0\24\0\1\0\2\0\0\0\b\0\4´\0\7¬\0\0\0\0\0\0";
  41.  
  42. public static byte[] generateIntReaderCode(Field f) {
  43. return new ByteArrayOutputStream(HEAD.length() + TAIL.length() + 100) {
  44. @SuppressWarnings("deprecation") byte[] get() {
  45. HEAD.getBytes(0, count = HEAD.length(), buf, 0);
  46. try(DataOutputStream dos = new DataOutputStream(this)) {
  47. String decl = f.getDeclaringClass().getName().replace('.', '/');
  48. dos.writeByte(1); dos.writeUTF(decl+"$"+f.getName()+"$access");
  49. dos.writeByte(1); dos.writeUTF(decl);
  50. dos.writeByte(1); dos.writeUTF(f.getName());
  51. } catch (IOException ex) {
  52. throw new UncheckedIOException(ex);
  53. }
  54. int dynSize = count;
  55. byte[] result = Arrays.copyOf(buf, dynSize + TAIL.length());
  56. TAIL.getBytes(0, TAIL.length(), result, dynSize);
  57. return result;
  58. }
  59. }.get();
  60. }
  61. }
Success #stdin #stdout 0.12s 36552KB
stdin
Standard input is empty
stdout
5