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

Avoid using shared resource streams between class loaders when extracting the native library. #578

Merged
merged 1 commit into from
Jun 27, 2021

Conversation

danysantiago
Copy link
Contributor

@danysantiago danysantiago commented Jan 16, 2021

This changes makes it so that we replace Class#getResourceAsStream() with a custom method that finds the resources and creates a stream but disables caching the stream. This is necessary in environments with where the native library has to be extracted and used with multiple class loaders that get closed.

Specifically, I was observing the following JDK-8205976 in a Gradle project with concurrent tasks that use sqlite-jdbc. The exact exception I was observing was:

java.io.IOException: Stream closed
        at java.base/java.util.zip.InflaterInputStream.ensureOpen(InflaterInputStream.java:68)
        at java.base/java.util.zip.InflaterInputStream.read(InflaterInputStream.java:143)
        at java.base/java.io.FilterInputStream.read(FilterInputStream.java:133)
        at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:252)
        at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:271)
        at org.sqlite.SQLiteJDBCLoader.contentsEquals(SQLiteJDBCLoader.java:179)
        at org.sqlite.SQLiteJDBCLoader.extractAndLoadLibraryFile(SQLiteJDBCLoader.java:243)
        at org.sqlite.SQLiteJDBCLoader.loadSQLiteNativeLibrary(SQLiteJDBCLoader.java:344)
        at org.sqlite.SQLiteJDBCLoader.initialize(SQLiteJDBCLoader.java:67)

Which lead me to JDK-8205976 after lots of logging. The test is a big complicated but sets ups the exact case for when this occurs. Multiple concurrent threads with isolated class loaders initializing the library for which the resource on all point to the same jar.

…ting the native library.

This changes makes it so that we replace Class#getResoirceAsStream() with a custom method that finds the resources and creates a stream but disables caching the stream. This is necessary in environments with where the native library has to be extracted and used with multiple class loaders that get closed.

Specifically, I was observing the following [JDK-8205976](https://bugs.openjdk.java.net/browse/JDK-8205976) in a [Gradle](https://gradle.org/) project with concurrent tasks that use sqlite-jdbc. The exact exception I was observing was:
```
java.io.IOException: Stream closed
        at java.base/java.util.zip.InflaterInputStream.ensureOpen(InflaterInputStream.java:68)
        at java.base/java.util.zip.InflaterInputStream.read(InflaterInputStream.java:143)
        at java.base/java.io.FilterInputStream.read(FilterInputStream.java:133)
        at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:252)
        at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:271)
        at org.sqlite.SQLiteJDBCLoader.contentsEquals(SQLiteJDBCLoader.java:179)
        at org.sqlite.SQLiteJDBCLoader.extractAndLoadLibraryFile(SQLiteJDBCLoader.java:243)
        at org.sqlite.SQLiteJDBCLoader.loadSQLiteNativeLibrary(SQLiteJDBCLoader.java:344)
        at org.sqlite.SQLiteJDBCLoader.initialize(SQLiteJDBCLoader.java:67)
 ```
 Which lead me to JDK-8205976 after lots of logging. The test is a big complicated but sets ups the exact case for when this occurs. Multiple concurrent threads with isolated class loaders initializing the library for which the resource on all point to the same jar.
Copy link

@yigit yigit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@danysantiago
Copy link
Contributor Author

Hi @xerial - Sorry to ping you, but is there a chance you can take a look at this PR, would love for it to get merged if possible. Thanks!

@xerial
Copy link
Owner

xerial commented Feb 8, 2021

ok. I wasn't aware of this bug https://bugs.openjdk.java.net/browse/JDK-8205976. Let me check

@xerial xerial self-assigned this Feb 8, 2021
@danysantiago
Copy link
Contributor Author

@xerial, just a friendly ping on this, hope you are well. Thank you!

@Mehly
Copy link

Mehly commented May 11, 2021

Looking forward to having this pull-request merged too, as it seems to be the reason why "Room" is not yet updating to sqlite-jdbc 3.34.0:

https://issuetracker.google.com/issues/174695268#comment8

Due to this reason, projects using "Room" only compile on Android-Studio-Canary (for Apple Silicon / ARM) when using the workaround that is described in the issue linked above.

@yigit
Copy link

yigit commented May 14, 2021

Hi @xerial , sorry for pinging here again, is there any chance of merging this and releasing a new version?
This became a bigger blocker for us AndroidX at this point (due to the adoption of Apple M1).

Let us know if we can help in any way.

@gauravk95
Copy link

@xerial it would be of great help, if you could merge this pull request. Those with M1 are having a tough time.

copybara-service bot pushed a commit to androidx/androidx that referenced this pull request Jun 8, 2021
* Update sqlite-jdbc to 3.34.0
* Use a custom loader in Room instead of SQLiteJDBCLoader since it
workarounds current issues in the loading strategy,
specifically: xerial/sqlite-jdbc#578.

Fixes: 177673291
Test: ./gradlew bOS
Change-Id: Idc597b734bc4d7bc03ffe938d2306b31193ada27
@snitsaruk
Copy link

Can this be merged?

@xerial xerial merged commit bf5e840 into xerial:master Jun 27, 2021
@xerial
Copy link
Owner

xerial commented Jun 27, 2021

Yes. Thanks for waiting. I'll release 3.35.0 soon.

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

Successfully merging this pull request may close these issues.

6 participants