security icon indicating copy to clipboard operation
security copied to clipboard

LinkageError in IdentityStore.validate()

Open hwellmann opened this issue 6 years ago • 3 comments

The use of MethodHandles in IdentityStore.validate() may lead to linkage errors.

This issue may occur in

MethodHandles.lookup()
    .bind(this, "validate", methodType(CredentialValidationResult.class, credential.getClass()))

when redeploying a web application.

In this case, methodType() may return a stale reference caused by the internal use of weak references which may still hang around if the classloader of the original deployment has not yet been garbage collected.

I ran into this problem when executing an Arquillian test suite on a remote server, where every test class gives rise to a new deployment. Observed on Java 8 as well as Java 11.

See https://github.com/hwellmann/method-type-leak for a self-contained test case.

Possible workaround:

Override IdentityStore.validate(Credential) in your custom class and downcast the Credentialargument to the concrete type.

hwellmann avatar Jan 24 '19 18:01 hwellmann

You're right, this is indeed a potential issue and the workaround is valid as you describe.

Maybe it's possible to (hint) force garbage collect the class loader. Not sure though. This issue could definitely need some help.

arjantijms avatar Jan 25 '19 09:01 arjantijms

Well, I'm afraid I don't understand enogh about method handles - the stale reference problem definitely is an issue at that level, and I don't know if that is by design or rather a bug (in the JDK, not in the Security API).

I'm not even sure that calling System.gc() guarantees that all weak references will be invalidated.

Possible approaches:

  1. Call System.gc() in IdentityStore.validate() before calling methodType(). (Ugly and overkill.)
  2. Wrap the MethodHandles stuff in a try-catch-block, catch IllegalAccessException, call System.gc() in the catch block and try again. (Still ugly.)
  3. Use reflection instead of method handles, optionally caching the result of the method lookup.
  4. Create an observer method for @Destroyed(ApplicationScoped.class) in the Security API implementation, and call System.gc() there, or invalidate the cache of option 3.

hwellmann avatar Jan 25 '19 16:01 hwellmann

@arjantijms As this looks like a bug or problem it may be due for the Jakarta EE 8 branch. What are the planned versions of Jakarta Security that should contribute to the next Jakarta EE releases? I closed a JCP Milestone, the next one is nicknamed 1.1, is that still correct?

keilw avatar May 27 '19 08:05 keilw