JEP 303 Sanity Check

August Nagro augustnagro at gmail.com
Mon Feb 17 05:04:07 UTC 2020


I think I have a cool use-case for the java.lang.constant API and JEP 303, Intrinsics for LDC and InvokeDynamic.

Imagine that you’re writing a deserialization library that for simplicity has a single method

T readValue(byte[] data, Class<T> cls).

The JSON libraries like Jackson have a similar API. Let's also assume that one of the methods is annotated with @Deserializer, and could be a constructor, static method, etc.

Jackson currently uses Reflection to find and invoke the @Deserializer method. This works, but direct bytecode generation with the Afterburner module yields ~70% performance improvement.

Creating MethodHandles ourselves will have the same performance as Reflection, since we cannot make them static final. But the MethodHandles we’re after are already in the constant pool. So what if instead, we:

1. Use reflection to find the method, generate a DynamicConstantDesc for the method, and cache in a Map<Class<?>, DynamicConstantDesc> for future readValue()s.

2. Get the MethodHandle with Intrinsics.ldc(), which compiles down to an actual ldc bytecode

3. invoke().



I watched Brian’s talk on JEP 303, and saw the example for loading int.class from the constant pool: 

DynamicConstantDesc<Class<?>> dcd1 =
	DynamicConstantDesc.ofNamed(BSM_PRIMITIVE_CLASS, "I", CD_Class);

// would use Intrinsics.ldc here instead of the reflective resolution when it becomes available.
Class<?> intCls = dcd1.resolveConstantDesc(lookup);

System.out.println(intCls); // prints ‘int'


But I’m struggling to construct a minimal example that loads a MethodHandle.. especially on the NameAndType part.


Anyway, is this a viable usecase? And any advice on using the new constant API would be helpful.

Regards,

August Nagro


More information about the hotspot-dev mailing list