com.dropchop.snakejar.embed.MainInterpreter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of snakejar Show documentation
Show all versions of snakejar Show documentation
A Java library with embedded Python (CPython) which supports native image compile and usage
in Java Application Servers, targeting native Python Machine Learning frameworks and libraries.
/**
* Copyright (c) 2015-2021 JEP AUTHORS.
*
* This file is licensed under the the zlib/libpng License.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
package com.dropchop.snakejar.embed;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
/**
* The main Python interpreter that all sub-interpreters will be created from.
* In a simpler embedded Python project, a single Python interpreter would be
* used and all would be good. However, since Jep supports multithreading with
* multiple sub-interpreters, we need the MainInterpreter to work around some
* issues.
*
* The MainInterpreter is used to avoid potential deadlocks. Python can deadlock
* when trying to acquire the GIL through methods such as PyGILState_*.
* While Jep does not use those methods, CPython extensions such as numpy do.
* The deadlock can occur if there is more than one PyThreadState per thread. To
* get around this, the MainInterpreter creates a unique thread that initializes
* Python and keeps this thread around forever. This ensures that any new
* sub-interpreters cannot be created on the same thread as the main Python
* interpreter.
*
* The MainInterpreter is also used to support shared modules. While each
* sub-interpreter is fairly sandboxed, in practice this does not always work
* well with CPython extensions. In particular, disposing of a sub-interpreter
* that has imported a CPython extension may cause some of the CPython
* extension's objects to be garbage collected. To get around this, shared
* modules import on the main interpreter's thread so they can be shared amongst
* sub-interpreters and will never be garbage collected.
*
* For more information about why the MainInterpreter class exists, see Sub-interpreter
* bugs and caveats.
*
*
* @author Nate Jensen
* @author Ben Steffensmeier
* @since 3.8
*/
public final class MainInterpreter implements AutoCloseable {
private static MainInterpreter instance = null;
private static PyConfig pyConfig = null;
private static String[] sharedModulesArgv = null;
private static String jepLibraryPath = null;
private Thread thread;
private BlockingQueue importQueue = new SynchronousQueue<>();
private BlockingQueue
© 2015 - 2025 Weber Informatics LLC | Privacy Policy