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

Re-use Java VM if it already exists #23

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

choplin
Copy link

@choplin choplin commented May 30, 2023

Context

JNI prohibits creating multiple Java VM within a single process. JNI_CreateJavaVM returns a JNI_EEXIST error if Java VM exists. In that case, we have to re-use the existing Java VM by calling JNI_GetCreatedJavaVMs.

What was changed?

  • Re-use the Java VM if it already exists by calling JNI_GetCreatedJavaVMs
  • Add classpath using URLClassLoader.addURL instead of -Xmx during runtime
    • This is required to add a classpath to the re-used existing Java VM

Other considerations

  • The re-used Java VM may have a different max heap size from the option value.
    • Since there is no way to change the max heap size of the running Java VM, we only show the current max heap size in the log message.

JNI prohibits creating multiple Java VM within a single process.
JNI_CreateJavaVM returns JNI_EEXIST error if Java VM already exists.
In that case, we have to re-use the existing Java VM by calling JNI_GetCreatedJavaVM.
@jopoly
Copy link

jopoly commented Dec 21, 2023

@choplin

Thanks for your contribution.
Could you please share specific scenario that JVM is created multiple times in the single process? Is there any issues have you met? As my understanding, the current source code already handled re-using JVM well if it is created.

jdbc_jvm_init()

        if (FunctionCallCheck == false)
        {
           create JVM
        }
        else
        {
           re-use existing JVM
        }

@choplin
Copy link
Author

choplin commented Dec 21, 2023

@jopoly Thank you for your reply!

Could you please share specific scenario that JVM is created multiple times in the single process?

Sorry for the lack of explanation. This becomes problematic when users use jdbc_fdw together with another extension that uses JNI too. Since Postgres worker works in a single process as you know, all extensions that use JNI must share a single JVM due to the limitation of JNI.

The mechanism you explained to prevent a duplicate call of JNI_CreateJavaVM utilizes a static variable in this extension as an initialized flag. So, it cannot prevent jdbc_fdw from calling JNI_CreateJavaVM even if another extension has already created a JVM, and vice versa.

For this kind of situation, JNI provides JNI_GetCreatedJavaVMs to reuse the existing JVM.

I understand there are not many extensions that use JNI. We encountered this situation when we tried to use jdbc_fdw with our extension, scalardb_fdw, that uses JNI to call Java library from Postgres.

@jopoly
Copy link

jopoly commented Dec 22, 2023

@choplin

Thanks for your explanation. I understood that multiple JVMs are not supported in the single process.

I understand there are not many extensions that use JNI. We encountered this situation when we tried to use jdbc_fdw with our extension, scalardb_fdw...

I'd like to re-produce the issue to understand more about the limitation of the current source code.
So, could you please share a test scenario including test model and test case?
Is it possible with the following test model?

                                            PostgreSQL     
                                          /            \
                                      jdbc_fdw       jdbc_fdw
                                        |                |
                                     PostgreSQL1     PostgreSQL2

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.

2 participants