Skip to content
szegedi edited this page Jan 1, 2015 · 3 revisions

Changes in 0.8 compared to 0.7

Summary

In almost year and a half that passed since 0.7 release, Dynalink has been quite successful as the cornerstone of the Nashorn JavaScript engine that is part of OpenJDK since Java 8. As such, it has matured a lot, and 0.8 is basically a release that brings the code on par with the version privately embedded into OpenJDK. The two versions are almost identical except for the package names, making it easy to prepare for eventual transition from a standalone version to the OpenJDK one. There is a separate document that outlines the differences between the OpenJDK version and the standalone version.

Major new features

  • GuardedInvocation can now have many SwitchPoints associated with it instead of at most one.
  • GuardedInvocation can now have a Throwable subclass associated with it. When linked, it will cause a MethodHandles.catchException combinator to be linked into the fallback chain. ChainedCallSite has reasonable default handling for when an exception is caught in that it will remove all exception handlers from its chain for the relinking in that case (as exception-driven linking should be opportunistic, and an exception should signal that a different strategy should be chosen).
  • LinkRequest.getCallSiteToken() API allows your linkers to retrieve a unique token associated with a call site. It can be used as a key in a weak map that a linker can maintain to attach history/profiling/etc. information to call sites.
  • DynamicLinkerFactory.setPrelinkFilter() API allows you to set a new kind of an object, a GuardedInvocationFilter on your master DynamicLinker for your language runtime. Such pre-link filters are useful to add final type conversions to the GuardedInvocation returned by GuardingDynamicLinker objects instead on relying on these individual linkers to to apply them. It basically moves the responsibility for adapting the invocation's return type to the call site type from individual guarding dynamic linkers to the master linker. This is a sensible design decision as the call site is under control of the master linker for the language runtime that created it, and the pre-link filter is also part of that linker.
  • GuardingTypeConverterFactory.convertToType() now returns a GuardedTypeConversion instead of a GuardedInvocation. This new type is a tuple of GuardedInvocation and a boolean flag that tells whether the invocation is allowed to be cached. Most type converting invocations are cacheable, but some should not be (notably, those that involve creation of adapter types when converting to Java SAM types).
  • DynamicLinkerFactory.setAutoConversionStrategy() allows setting of a new strategy, a MethodTypeConversionStrategy on a dynamic linker that allows customization of automatic type conversions that should happen after language specific type conversions. A typical use for this is allowing unboxing conversions and specifying what happens when null is unboxed.

Minor new features

  • LinkRequest.getLinkCount() API will tell you the number of times the currently linked call site has been relinked.
  • LinkerServicesImpl.getCurrentLinkRequest() retrieves the currently linked request on the current thread. While this is normally passed around as a method parameter, it sometimes needs to be accessed from a context where the parameter is not feasible to be passed. The invocation of this method is tied to the RuntimePermission("dynalink.getCurrentLinkRequest") permission check when Dynalink runs in a JVM with a security manager. It needs to be protected by a permission check as the link request allows access to the currently linked call site's MethodHandles.lookup() object, which is a security capability.

Improvements and fixes

  • A lot of security tightenings. Since in OpenJDK world, Dynalink is part of the trusted code base, it needs to be extra careful to make sure it is secure. This includes making sure only narrowest sets of privileges are requested in doPrivileged blocks etc.
  • Handling of single argument in vararg array position now works as expected in presence of language-specific conversions that allow conversion of language-specific objects to Java arrays. That is, if your language allows its native arrays to be converted into Java arrays, and you pass such a native array in the last argument position to invocation of a variable arity Java method, the native array will get converted to the appropriate Java array.
  • A corner case in handling caller sensitive methods has been fixed.

Backwards incompatible changes

Unfortunately, there are some. Overall, the API has evolved for the better and I had to break some eggs to make this omelette.

  • GuardedInvocation.compose(MethodHandle,MethodHandle) is gone, in its place is now GuardedInvocation.compose(MethodHandle,MethodHandle,MethodHandle) (introducing a fallback for a catch combinator) but if you are using it be aware that it isn't a simple matter of just adding a new argument, the meaning of the first two arguments was reversed too, so adjust your code.
  • GuardedInvocation.getSwitchPoint() is gone. In its place is now GuardedInvocation.getSwitchPoints() which returns SwitchPoint[] instead of a single SwitchPoint.
  • GuardingTypeConverterFactory.convertToType() now returns a GuardedTypeConversion instead of a GuardedInvocation.
  • void type is not considered to be automatically convertible in a lossless manner to any other type. The semantics of converting void to any other type are language specific. For example, in JavaScript, the natural representation for void is undefined, rather than null.
  • No reference type is considered to be automatically convertible in a lossless manner to any primitive type (e.g. no automatic unboxing of Integer to int), as the semantics of null unboxing are language specific. Some languages might allow null to become 0, false, or some other value, while other languages would want a NPE thrown.
Clone this wiki locally