Add control of JVM startup options

This commit is contained in:
James Laird 2014-05-09 17:22:56 +10:00
parent 19d4ddc45d
commit 2910e2fddc
5 changed files with 120 additions and 37 deletions

View File

@ -327,3 +327,19 @@ example::
Signature: ()V
}
JVM options and the class path
------------------------------
JVM options need to be set before `import jnius` is called, as they cannot be changed after the VM starts up.
To this end, you can::
import jnius_config
jnius_config.add_options('-Xrs', '-Xmx4096')
jnius_config.set_classpath('.', '/usr/local/fem/plugins/*')
import jnius
If a classpath is set with these functions, it overrides any CLASSPATH environment variable.
Multiple options or path entries should be supplied as multiple arguments to the `add_` and `set_` functions.
If no classpath is provided and CLASSPATH is not set, the path defaults to `'.'`.
This functionality is not available on Android.

View File

@ -4,11 +4,13 @@ cdef JNIEnv *default_env = NULL
cdef extern int gettid()
cdef JavaVM *jvm = NULL
cdef JNIEnv *get_jnienv():
cdef JNIEnv *get_jnienv() except NULL:
global default_env
# first call, init.
if default_env == NULL:
default_env = get_platform_jnienv()
if default_env == NULL:
return NULL
default_env[0].GetJavaVM(default_env, &jvm)
# return the current env attached to the thread

View File

@ -4,6 +4,7 @@
cdef extern jint __stdcall JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args)
cdef extern from "jni.h":
int JNI_VERSION_1_4
int JNI_OK
jboolean JNI_FALSE
ctypedef struct JavaVMInitArgs:
jint version
@ -16,52 +17,36 @@ cdef extern from "jni.h":
cdef JNIEnv *_platform_default_env = NULL
def classpath():
import platform
from glob import glob
from os import environ
from os.path import realpath, dirname, join
if platform.system() == 'Windows':
split_char = ';'
else:
split_char = ':'
paths = [realpath('.'), join(dirname(__file__), 'src'), ]
if 'CLASSPATH' not in environ:
return split_char.join(paths)
cp = environ.get('CLASSPATH')
pre_paths = paths + cp.split(split_char)
# deal with wildcards
for path in pre_paths:
if not path.endswith('*'):
paths.append(path)
else:
paths.extend(glob(path + '.jar'))
paths.extend(glob(path + '.JAR'))
result = split_char.join(paths)
return result
cdef void create_jnienv():
cdef void create_jnienv() except *:
cdef JavaVM* jvm
cdef JavaVMInitArgs args
cdef JavaVMOption options[1]
cdef JavaVMOption *options
cdef int ret
cdef bytes py_bytes
import jnius_config
cp = classpath()
py_bytes = <bytes>('-Djava.class.path={0}'.format(cp))
options[0].optionString = py_bytes
options[0].extraInfo = NULL
optarr = jnius_config.options
optarr.append("-Djava.class.path=" + jnius_config.expand_classpath())
options = <JavaVMOption*>malloc(sizeof(JavaVMOption) * len(optarr))
for i, opt in enumerate(optarr):
options[i].optionString = <bytes>(opt)
options[i].extraInfo = NULL
args.version = JNI_VERSION_1_4
args.options = options
args.nOptions = 1
args.nOptions = len(optarr)
args.ignoreUnrecognized = JNI_FALSE
JNI_CreateJavaVM(&jvm, <void **>&_platform_default_env, &args)
ret = JNI_CreateJavaVM(&jvm, <void **>&_platform_default_env, &args)
free(options)
cdef JNIEnv *get_platform_jnienv():
if ret != JNI_OK:
raise SystemError("JVM failed to start")
jnius_config.vm_running = True
cdef JNIEnv *get_platform_jnienv() except NULL:
if _platform_default_env == NULL:
create_jnienv()
return _platform_default_env

79
jnius_config.py Normal file
View File

@ -0,0 +1,79 @@
__all__ = ('set_options', 'add_options', 'get_options',
'set_classpath', 'add_classpath', 'get_classpath',
'expand_classpath')
import platform
if platform.system() == 'Windows':
split_char = ';'
else:
split_char = ':'
vm_running = False
options = []
classpath = None
def set_options(*opts):
"Sets the list of options to the JVM. Removes any previously set options."
if vm_running:
raise ValueError("VM is already running, can't set options")
globals()['options'] = opts
def add_options(*opts):
"Appends options to the list of VM options."
if vm_running:
raise ValueError("VM is already running, can't set options")
global options
options.extend(opts)
def get_options():
"Retrieves the current list of VM options."
global options
return list(options)
def set_classpath(*path):
"""
Sets the classpath for the JVM to use. Replaces any existing classpath, overriding the CLASSPATH environment variable.
"""
if vm_running:
raise ValueError("VM is already running, can't set classpath")
global classpath
classpath = path
def add_classpath(*path):
"""
Appends items to the classpath for the JVM to use.
Replaces any existing classpath, overriding the CLASSPATH environment variable.
"""
if vm_running:
raise ValueError("VM is already running, can't set classpath")
global classpath
if classpath is None:
classpath = list(path)
else:
classpath.extend(path)
def get_classpath():
"Retrieves the classpath the JVM will use."
from os import environ
from os.path import realpath
global classpath
if classpath is not None:
return list(classpath)
if 'CLASSPATH' in environ:
return environ['CLASSPATH'].split(split_char)
return [realpath('.')]
def expand_classpath():
from glob import glob
paths = []
# deal with wildcards
for path in get_classpath():
if not path.endswith('*'):
paths.append(path)
else:
paths.extend(glob(path + '.[Jj][Aa][Rr]'))
return split_char.join(paths)

View File

@ -108,6 +108,7 @@ setup(name='jnius',
version=version,
cmdclass={'build_ext': build_ext},
packages=['jnius'],
py_modules=['jnius_config'],
url='http://pyjnius.readthedocs.org/',
author='Mathieu Virbel and Gabriel Pettier',
author_email='mat@kivy.org,gabriel@kivy.org',