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

'ConsoleWriter cannot be instantiated reflectively' with graal #127

Closed
MarkusKramer opened this issue Nov 24, 2019 · 6 comments
Closed

'ConsoleWriter cannot be instantiated reflectively' with graal #127

MarkusKramer opened this issue Nov 24, 2019 · 6 comments
Labels
bug

Comments

@MarkusKramer
Copy link

@MarkusKramer MarkusKramer commented Nov 24, 2019

I'm building CLI application that I would like to compile with graal to a native image. Tinylog seems like a great fit to keep the image small.

But the graal compiler fails on tinylog with:
Fatal error: java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: Class org.tinylog.writers.ConsoleWriter cannot be instantiated reflectively . It does not have a nullary constructor.
Using tinylog 2.0.0 and graalvm-ce-java11-19.3.0.

It saw that you have implemented a custom service loading logic in org.tinylog.configuration.ServiceLoader. I think the tinylog JAR is not standards compliant, and thus makes graal (and possibly other tools) fail.

@pmwmedia

This comment has been minimized.

Copy link
Owner

@pmwmedia pmwmedia commented Nov 25, 2019

@MarkusKramer Could you provide an minimal example project? I haven't used Graal VM before and would like to reproduce the error.

@pmwmedia pmwmedia added the bug label Nov 25, 2019
@MarkusKramer

This comment has been minimized.

Copy link
Author

@MarkusKramer MarkusKramer commented Nov 25, 2019

I'll see if can prepare something. But I think the problem is not really related to Graal.

My theory:
The tinylog jar has files in META-INF/services. But these reference classes that are missing a public no argument constructor. Which is a violation of the java service provider spec. See https://docs.oracle.com/javase/9/docs/api/java/util/ServiceLoader.html

A simple solution would be to rename your directory from META-INF/services to just "services".

@MarkusKramer

This comment has been minimized.

Copy link
Author

@MarkusKramer MarkusKramer commented Nov 25, 2019

Beyond this bug, I think a plain java way of configuring tinylog and without any auto-magic configuration would be beneficial. If the code can be completely statically analysed it makes live with tools like Graal or the maven shade plugin (with minify option on) much easier and the resulting artifact as small as possible.

@pmwmedia

This comment has been minimized.

Copy link
Owner

@pmwmedia pmwmedia commented Nov 27, 2019

The best way would be to introduce builders with default constructors for creating logging providers, writers, and policies. The disadvantage is that the number of classes will be doubled (on builder for each logging provider, writer, and policy), but then we can get rid of the custom service loader implementation of tinylog. This will also solve the issue with the current ProGuard version, described in #126. As this will be an architectural break, I can do only in the next major release with tinylog 3.

For tinylog 2.1, I will try to add a default constructor to every writer and policy, if it will solve the problem with Graal.

@pmwmedia

This comment has been minimized.

Copy link
Owner

@pmwmedia pmwmedia commented Nov 27, 2019

@MarkusKramer Could you test, if the attached JARs work with Graal? All services Implementations have default constructors now.

tinylog-2.0-SNAPSHOT.zip

pmwmedia added a commit that referenced this issue Nov 27, 2019
@MarkusKramer

This comment has been minimized.

Copy link
Author

@MarkusKramer MarkusKramer commented Nov 27, 2019

Thanks for the quick patch. I gave it a try and it solved the issue. However, I'm getting a new error now :-)
Error: com.oracle.graal.pointsto.constraints.UnresolvedElementException: Discovered unresolved type during parsing: org.tinylog.Supplier. To diagnose the issue you can use the --allow-incomplete-classpath option. The missing type is then reported at run time when it is accessed the first time.

If I use the "--allow-incomplete-classpath" option it fails at runtime with Exception in thread "main" java.lang.NoClassDefFoundError: org.tinylog.Supplier

Due to issues with other libraries I won't pursue using Graal further - for the moment. Thus, you don't need to fix this for me. But I guess Graal support would be a nice use case for tinylog as using log4j2 would probably be even more difficult.

pmwmedia added a commit that referenced this issue Nov 27, 2019
@pmwmedia pmwmedia closed this Nov 30, 2019
pmwmedia added a commit that referenced this issue Dec 1, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.