Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StackOverflow in AbstractExtensionFinder.findExtensionAnnotation() #363

Closed
metaschell opened this issue Jan 25, 2020 · 5 comments
Closed
Assignees
Labels

Comments

@metaschell
Copy link

I create an extension and registered it using the extension.idx file and the class is properly loaded. My class has no @Extension annotation though (this should stay like this, I manually created the extensions.idx file), but when scanning for the @Extension annotation in
org.pf4j.AbstractExtensionFinder.findExtensionAnnotation(Class<?>) the findExtensionAnnotation() method is calling itself recursively. Theoretically, it should simply return null if there is no such annotation, but the problem here is that if there are any other annotations this leads to a StackOverflowError as any other annotation would have any of the java.lang.annotations annotations such as @Scope, @Retention, and @Documented which in turn uses these three annotations again:
@MyAnnotation -> @Retention -> @Documented -> @Retention -> @Documented ...

A potential solution would be to not do the recursion for any annotation in the java.lang.* packages.

BTW, it is difficult to work around this problem as all methods are private so they cannot be overridden in order to catch the problem and move on. I understand that this is a philosophical question regarding hiding vs. (partially) exposing internals, but currently there is no way around that unless overriding all of org.pf4j.AbstractExtensionFinder.find(String) with all related methods...

(Partial) Stacktrace:

Caused by: java.lang.StackOverflowError: null
at java.util.LinkedHashMap$LinkedHashIterator.(LinkedHashMap.java:706) ~[na:1.8.0_222]
at java.util.LinkedHashMap$LinkedValueIterator.(LinkedHashMap.java:745) ~[na:1.8.0_222]
at java.util.LinkedHashMap$LinkedValues.iterator(LinkedHashMap.java:596) ~[na:1.8.0_222]
at java.util.AbstractCollection.toArray(AbstractCollection.java:180) ~[na:1.8.0_222]
at sun.reflect.annotation.AnnotationParser.toArray(AnnotationParser.java:865) ~[na:1.8.0_222]
at java.lang.Class.getAnnotations(Class.java:3446) ~[na:1.8.0_222]
at org.pf4j.AbstractExtensionFinder.findExtensionAnnotation(AbstractExtensionFinder.java:357) ~[na:na]
at org.pf4j.AbstractExtensionFinder.findExtensionAnnotation(AbstractExtensionFinder.java:359) ~[na:na]
at org.pf4j.AbstractExtensionFinder.findExtensionAnnotation(AbstractExtensionFinder.java:359) ~[na:na]
at org.pf4j.AbstractExtensionFinder.findExtensionAnnotation(AbstractExtensionFinder.java:359) ~[na:na]
at org.pf4j.AbstractExtensionFinder.findExtensionAnnotation(AbstractExtensionFinder.java:359) ~[na:na]
at org.pf4j.AbstractExtensionFinder.findExtensionAnnotation(AbstractExtensionFinder.java:359) ~[na:na]
at org.pf4j.AbstractExtensionFinder.findExtensionAnnotation(AbstractExtensionFinder.java:359) ~[na:na]
at org.pf4j.AbstractExtensionFinder.findExtensionAnnotation(AbstractExtensionFinder.java:359) ~[na:na]
at org.pf4j.AbstractExtensionFinder.findExtensionAnnotation(AbstractExtensionFinder.java:359) ~[na:na]
at org.pf4j.AbstractExtensionFinder.findExtensionAnnotation(AbstractExtensionFinder.java:359) ~[na:na]
at org.pf4j.AbstractExtensionFinder.findExtensionAnnotation(AbstractExtensionFinder.java:359) ~[na:na]
at org.pf4j.AbstractExtensionFinder.findExtensionAnnotation(AbstractExtensionFinder.java:359) ~[na:na]
at org.pf4j.AbstractExtensionFinder.findExtensionAnnotation(AbstractExtensionFinder.java:359) ~[na:na]
...

Example class:
(note the class would rather implement an interface extending ExtensionPoint, but that should not make a difference here)

package com.example;

import org.pf4j.ExtensionPoint;

@SomeAnnotation
public class ExampleExtension implements ExtensionPoint {
    public void doSomething() {
        System.out.println("Hello, world");
    }
}

Registration file (META-INF/extensions.idx)

com.example.ExampleExtension
@decebals
Copy link
Member

decebals commented Feb 4, 2020

@metaschell
Sorry, but I completely missed this issue.
I think that I understand your problem. The AbstractExtensionFinder.findExtensionAnnotation method was introduced by #348:
image

A potential solution would be to not do the recursion for any annotation in the java.lang.* packages.

I think that for the moment this is the best solution (simple and without to many modifications). Can you submit a PR?

In the future I hope to avoid reflection for this part of PF4J (find extensions). We have all the information (extensions classes, extensions orders, extensions points) at compilation time (in annotation processor) and we can reuse them at runtime (see #207).

@decebals
Copy link
Member

@metaschell
If you want to submit a PR would be nice. If you don't have time I will try to do it myself.
My intention is to release a new version in few days.

@decebals decebals added the bug label Apr 14, 2020
@metaschell
Copy link
Author

@decebals I will likely not have time in the next two weeks so if you would like to have that fixed by then, feel free to go ahead. We have a local workaround in place

@metaschell
Copy link
Author

In the future I hope to avoid reflection for this part of PF4J (find extensions). We have all the information (extensions classes, extensions orders, extensions points) at compilation time (in annotation processor) and we can reuse them at runtime (see #207).

This is only the case if you actually use the annotation processor in the build which is not necessarily always the case...

In our project we basically only use a custom ServiceLoader-based ExtensionFinder now.

@jetztgradnet
Copy link

Nice, thanks for fixing!
We are using a different approach now, but it is still good to see this closed, as other might stumble over the same issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants