Skip to content

Commit

Permalink
Another attempt using an agent
Browse files Browse the repository at this point in the history
  • Loading branch information
Thrameos committed Jun 23, 2024
1 parent 49c3bde commit 902156a
Show file tree
Hide file tree
Showing 7 changed files with 28 additions and 56 deletions.
5 changes: 5 additions & 0 deletions jpype/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,11 @@ def startJVM(
if classpath:
extra_jvm_args += (f'-Djava.class.path={_handleClassPath(classpath)}', )

supportLib = os.path.join(os.path.dirname(os.path.dirname(__file__)),"org.jpype.jar")
if not os.path.exists(supportLib):
raise RuntimeError("Unable to find org.jpype.jar support library at "+supportLib)
extra_jvm_args += ('-javaagent:'+supportLib,)

try:
import locale
# Gather a list of locale settings that Java may override (excluding LC_ALL)
Expand Down
58 changes: 3 additions & 55 deletions native/common/jp_classloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,13 @@
#include <jpype.h>
#include <pyjp.h>
#include <jp_classloader.h>
#include <filesystem>

jobject JPClassLoader::getBootLoader()
{
return m_BootLoader.get();
}

static jobject toURL(JPJavaFrame &frame, const string& path)
{
// file = new File("org.jpype.jar");
jclass fileClass = frame.FindClass("java/io/File");
jmethodID newFile = frame.GetMethodID(fileClass, "<init>", "(Ljava/lang/String;)V");
jvalue v[3];
v[0].l = frame.NewStringUTF(path.c_str());
jobject file = frame.NewObjectA(fileClass, newFile, v);

// url = file.toURI().toURL();
jmethodID toURI = frame.GetMethodID(fileClass, "toURI", "()Ljava/net/URI;");
jobject uri = frame.CallObjectMethodA(file, toURI, nullptr);
jclass uriClass = frame.GetObjectClass(uri);
jmethodID toURL = frame.GetMethodID(uriClass, "toURL", "()Ljava/net/URL;");
return frame.CallObjectMethodA(uri, toURL, nullptr);
}

JPClassLoader::JPClassLoader(JPJavaFrame& frame)
{
JP_TRACE_IN("JPClassLoader::JPClassLoader");
Expand Down Expand Up @@ -68,44 +52,8 @@ JPClassLoader::JPClassLoader(JPJavaFrame& frame)
}
frame.ExceptionClear();

// Harder, we need to find the _jpype module and use __file__ to obtain a
// path.
JPPyObject pypath = JPPyObject::call(PyObject_GetAttrString(PyJPModule, "__file__"));
string path = JPPyString::asStringUTF8(pypath.get());
string::size_type i = path.find_last_of('\\');
if (i == string::npos)
i = path.find_last_of('/');
if (i == string::npos)
JP_RAISE(PyExc_RuntimeError, "Can't find jar path");
path = path.substr(0, i + 1);
jobject url1 = toURL(frame, path + "org.jpype.jar");
// jobject url2 = toURL(frame, path + "lib/asm-8.0.1.jar");

// urlArray = new URL[]{url};
jclass urlClass = frame.GetObjectClass(url1);
jobjectArray urlArray = frame.NewObjectArray(1, urlClass, nullptr);
frame.SetObjectArrayElement(urlArray, 0, url1);
// frame.SetObjectArrayElement(urlArray, 1, url2);

// cl = new URLClassLoader(urlArray);
jclass urlLoaderClass = frame.FindClass("java/net/URLClassLoader");
jmethodID newURLClassLoader = frame.GetMethodID(urlLoaderClass, "<init>", "([Ljava/net/URL;Ljava/lang/ClassLoader;)V");
jvalue v[3];
v[0].l = (jobject) urlArray;
v[1].l = (jobject) m_SystemClassLoader.get();
jobject cl = frame.NewObjectA(urlLoaderClass, newURLClassLoader, v);

// Class dycl = Class.forName("org.jpype.classloader.DynamicClassLoader", true, cl);
v[0].l = frame.NewStringUTF("org.jpype.classloader.DynamicClassLoader");
v[1].z = true;
v[2].l = cl;
auto dyClass = (jclass) frame.CallStaticObjectMethodA(m_ClassClass.get(), m_ForNameID, v);

// dycl.newInstance(systemClassLoader);
jmethodID newDyLoader = frame.GetMethodID(dyClass, "<init>", "(Ljava/lang/ClassLoader;)V");
v[0].l = cl;
m_BootLoader = JPObjectRef(frame, frame.NewObjectA(dyClass, newDyLoader, v));

// org.jpype was not loaded already so we can't proceed
JP_RAISE(PyExc_RuntimeError, "Can't find org.jpype.jar support library");
JP_TRACE_OUT; // GCOVR_EXCL_LINE
}

Expand Down
2 changes: 2 additions & 0 deletions native/java/manifest.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Manifest-Version: 1.0
Premain-Class: org.jpype.agent.JPypeAgent
10 changes: 10 additions & 0 deletions native/java/org/jpype/agent/JPypeAgent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.jpype.agent;

import java.lang.instrument.Instrumentation;

public class JPypeAgent
{
public static void premain(String agentArgs, Instrumentation inst) {
System.out.println("Start jpype");
}
}
2 changes: 2 additions & 0 deletions project/jpype_java/manifest.mf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Manifest-Version: 1.0
Premain-Class: org.jpype.agent.JPypeAgent
1 change: 1 addition & 0 deletions project/jpype_java/nbproject/project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,4 @@ source.encoding=UTF-8
src.java.dir=${file.reference.native-java}
test.harness.dir=${file.reference.test-harness}
test.src.dir=test
manifest.file=manifest.mf
6 changes: 5 additions & 1 deletion setupext/build_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,8 +315,12 @@ def build_java_ext(self, ext):
os.makedirs("build/classes", exist_ok=True)
self.announce(" %s" % " ".join(cmd1), level=distutils.log.INFO)
subprocess.check_call(cmd1)
manifest = None
try:
for file in glob.iglob("native/java/**/*.*", recursive=True):
if file.endswith("manifest.txt"):
manifest = file
continue
if file.endswith(".java") or os.path.isdir(file):
continue
p = os.path.join(build_dir, os.path.relpath(file, "native/java"))
Expand All @@ -326,7 +330,7 @@ def build_java_ext(self, ext):
print("FAIL", ex)
pass
cmd3 = shlex.split(
'%s cvf "%s" -C "%s" .' % (jar, jarFile, build_dir))
'%s cvfm "%s" "%s" -C "%s" .' % (jar, jarFile, manifest, build_dir))
self.announce(" %s" % " ".join(cmd3), level=distutils.log.INFO)
subprocess.check_call(cmd3)

Expand Down

0 comments on commit 902156a

Please sign in to comment.