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

Access to default methods in @JImplements #1182

Merged
merged 16 commits into from
Oct 24, 2024

Conversation

Thrameos
Copy link
Contributor

Default methods are a pain because the proxy to interfaces always redirects and there is no "normal" method of accessing such a method via reflection. The PR uses MethodHandles to perform the redirect. It is no clear if this works in Java 8 though as some of the comments regarding this method indicate that it may be a Java 9 feature. I added test cases to see if this is true. If it is only a Java 9 feature we can try to implement a mixed mode jar file, but that will get more complicated.

Fixes #1181

@Thrameos
Copy link
Contributor Author

Will be hard to get this to work as the jar file must be loaded into the base classloader. It may be doable, but will require serious effort.

@marscher
Copy link
Member

marscher commented May 7, 2024

sorry I cannot estimate if it'd be worth the effort? How common are these "default methods"?

@Thrameos
Copy link
Contributor Author

Thrameos commented May 7, 2024

Default methods are a newer feature of Java in which the programmers adds some functionality to an interface which will automatically be available to the implemented classes. They are common in newer code, but most of the Java library classes currently don't use them. They are difficult to access because they didn't exist when JNI was written so there is no "call the default" method and the proxy system works against them. The issue here is that the newer java security methods prevent calling code from arbitrary modules, and our jar is not located in a position of any privilege as we are not in the boot loader.

About the only way I can make this happen would be to make my own Jar loader which uses the JNI special under the table class definition method which in theory would get the JPype into a lower level. However, JNI doesn't really have any support for modules or module definition so I have no idea if I can actually get to the level required to make this type of access. Making a jar side loader would require access to gzip and tar access. There may be severe technical issues if I need to load the class files in a particular order.

One can expect that many libraries will have default method if they use interfaces at some point. Thus there is some value, but it is a large lift (and given I am underwater until July it won't happen soon.)

@marscher
Copy link
Member

marscher commented May 8, 2024

Bypassing JVMs security mechanisms does not seem right. If these extended Interfaces do not posses a mechanism in JNI, we should request them upstream. It does not make any sense for them to be inacessible, right?

Why are default methods not already handled by the MRO, e.g. calling the parents implementation? Actually it should, should it not?
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8033126

@Thrameos
Copy link
Contributor Author

Thrameos commented May 8, 2024 via email

@Thrameos
Copy link
Contributor Author

I am still trying to come up with a solution for this. The Java9 security model is the source of the issues. Certain actions require that the code be loaded into the lowest layer of the JVM and be contained in an authorized module. There was no thought as to how the JNI layer interacts as it doesn't have a module nor is formally loaded into the ClassLoader other than by class which invoked it first.

A lot of stuff we have yet to be able to support such as calling default methods, calling protected methods/accessing protected members when extending a class are all stuck on this same common element. Without appropriate privileges all calls end up as second class and are denied.

I have tried a number of different ways to work around this:

  1. Force the org.jpype.jar into the classpath.
    Doable, but argues with the user specified classpath. This is mostly a problem of the grandfathered and should have been deprecated "-Dclasspath=XXX" startJVM option. As we have to massage the classpath the user provided there are a lot of edge cases. As best, I can make the startJVM through and error on manually setting the classpath, but I am sure that will break a lot of old code.

  2. Try to install the jar classes under the JVM using JNI DefineClass. This is doable but runs into clear problems as some classes use resources which don't exist when loaded that method. And second all hell breaks lose if the jar is loaded through both the dynamic loader and the define class method for some reason. I have thus abandoned this.

  3. Use an agent to allow "late" loading of classes in the class path. This method would use Instrumentation API to slip jar files in after the JVM is started. The "org.jpype" jar would just use this path to install itself and we can insert other jars so that multiple calls to startJVM would to the same. Again the problem here is conflict. To use an agent I would have ship a second jar file org.jpype.agent.jar which grants us the superpowers we need. But there are times (rare) that a person actually installs an agent through startJVM and in those cases we will have conflicts. I can give agent that same treatment that classpath got where the user is not setting things directly but through an API which can resolve conflicts.

I did some testing on the javaagent option. As far as I can tell noone outside of my group makes use of agents in the startJVM() (at least no google searches show an intersection). The only time that it gets used in my group is when doing certain profiling tasks.

Looking deeper I think that agent may solve the problem though in a weird way. You can start multiple agents with the repeated arguments so it isn't like java.class.path. Second it appears that if we simply make org.jpype.jar an agent (even if it doesn't do anything) it will automatically be promoted to a level were we can access reflection freely.

The problem with the JVM classpath security model is that assumes that everything must be known at start of JVM and thus the only jars that can be trusted exist at that time. Many jar types that provide services just don't work after the JVM is started. I have not found any API which allows the JNI controlling process which spawned the JVM to control the access privileges. The entire model of the JVM is "one and done" for any and all settings.

I am guessing that is either laziness on the part of JVM developers (this is edge case stuff and we have better things to do), neglect (which JNI is clearly suffering from), or some lame attempt at security from back when the JVM was still running in browsers and people were sandbox breaking. Regardless of the case, it gives us the classic "sucks to be you" feeling as seeming reasonable requests just can't be met. It makes me long for that far future in which graalvm or web assembly VM simply provides a language independent platform which Python and Java can play nicely.

@Thrameos
Copy link
Contributor Author

@marscher I think this one may be working now. But we need other PR to get test matrix back on line first.

@Thrameos Thrameos requested a review from marscher June 24, 2024 16:50
Copy link
Contributor Author

@Thrameos Thrameos left a comment

Choose a reason for hiding this comment

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

As this PR is a lot to chew on, I have highlighted the critical sections.

jpype/_core.py Outdated Show resolved Hide resolved
native/common/jp_classloader.cpp Show resolved Hide resolved
native/common/jp_proxy.cpp Show resolved Hide resolved
native/java/org/jpype/agent/JPypeAgent.java Show resolved Hide resolved
Comment on lines 104 to 107
return MethodHandles.lookup()
.unreflectSpecial(method, method.getDeclaringClass())
.bindTo(proxy)
.invokeWithArguments(args);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the heart of the change as we need to call these privileged methods to invoke a special method. Of course given the method we are trying to invoke is nothing more than a public method implemented in the interface there is absolutely nothing privileged about the call. The issue is simply that the API through which we are accessing a public method can also be used to invoke private methods.

Copy link
Contributor

@astrelsky astrelsky Sep 12, 2024

Choose a reason for hiding this comment

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

Wouldn't using MethodHandles.publicLookup be better here since it can only access public fields/methods thus removing the privileged issue?

I'm sure there are some possible benefits to having a java agent, I just wanted to point this out.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can certainly try that. Though we will still need the agent if we want to make sure that it never changes behavior based on how JPype is started. (Something that plagues the development.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The other reason for requiring privilege is if we ever want to be able to "extend" a class in Python. In that case we will need to get to protected methods, and protected fields.

Copy link
Contributor

@astrelsky astrelsky Sep 12, 2024

Choose a reason for hiding this comment

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

The other reason for requiring privilege is if we ever want to be able to "extend" a class in Python. In that case we will need to get to protected methods, and protected fields.

I actually have a prototype using JDK22 ClassFile API preview feature, as an independent python package, where I managed this. I designed it around the impression that if you want to extend a Java class from Python, then you don't care about the added overhead 😅.

I basically created delegate methods that start with "-" which could only be accessed by reflection or it would be a syntax error. It's gross but it worked.

I was considering integrating and contributing it since it would not introduce GPL code. Was just waiting on it to exit preview in a LTS JDK and then for the free time.

Copy link
Contributor

Choose a reason for hiding this comment

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

You should be able to call a default method from jni using CallNonvirtualObjectMethodA if you use the interface with the default method as the claz parameter.

I figured this out while working on super() support for extension classes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

CallNonvirtualObjectMethodA does not work. I ran tests on it. While it does allow the default method to be called, it ALWAYS calls the default even when overwritten. I thus went with this approach as there are no methods in the JNI interface that gave proper behavior.

Copy link
Contributor

@astrelsky astrelsky Sep 30, 2024

Choose a reason for hiding this comment

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

CallNonvirtualObjectMethodA does not work. I ran tests on it. While it does allow the default method to be called, it ALWAYS calls the default even when overwritten. I thus went with this approach as there are no methods in the JNI interface that gave proper behavior.

Yes that is what the NonVirtual does, it's invoke exactly the specified method. Thinking about it, I'm not sure why the regular CallVirtual doesn't work.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The reason it doesn't is that for interfaces "ALL" virtual method route to the proxy dispatch. As default methods are virtual that means they effectively are not reachable other than by the "NonVirtual" method. We could in principle your the virtual call request to our method, then call to Python with a reference handle find out that it was really supposed to go to default, then reroute back in the JNI method for a NonVirtual call. That would mean unpacking and repacking arguments at C level and keeping track of the default level in C. Of course we would have to know to try the nonvirtual path (trying to call it when it doesn't exist is a segfault). So that means everything needs to be handed to the the C method. I attempted that path but found it distasteful as it required making reflection API calls prior to launching to C.

It is "doable" but means more routing on the primary path to check for and passing the default method down to C. That would make this already slow path potentially even slower for a feature that not many people will likely use. Better to reroute back to Java and try to invoke the handle there.

native/java/org/jpype/proxy/JPypeProxy.java Show resolved Hide resolved
setupext/build_ext.py Show resolved Hide resolved
@astrelsky
Copy link
Contributor

astrelsky commented Sep 11, 2024

I just wanted to put this option out here

InvocationHandler.invokeDefault was introduced in JDK 16. You could access the method through reflection if using JDK 16 or newer and either throw an exception otherwise, or investigate how it's achieved in the Proxy class and see if it's manageable to do in JDK 8.

If I remember correctly you can open a module at runtime, assuming you don't just slap on the --add-opens when starting the JVM (I've not looked at how jpype does this). That should get you access to whatever Java internals you're trying to get at, although I don't think it's the best solution.

I understand that there needs to be support for JDK 8, but if you're using a 10 year old version of the JDK, that's on you. Things for newer JDK versions can be accessed via reflection with a negligible amount of additional overhead. If a user wants to use these features but can't, then maybe they should stop using winxp outdated JDKs.

@astrelsky
Copy link
Contributor

astrelsky commented Sep 11, 2024

Regarding illegal reflective access. For the LTS JDKs it works as follows:

  • JDK 8: Allowed
  • JDK 11: Allowed by default with runtime warning. (Changeable via command line argument)
  • JDK 17+: Denied

So for this specific instance, you can use the JDK16+ method when available and use illegal reflective access otherwise.

There is a table with access information here. I couldn't figure out how to link to the section but it's a little more then halfway down the page.
https://blogs.oracle.com/javamagazine/post/a-peek-into-java-17-continuing-the-drive-to-encapsulate-the-java-runtime-internals

@Thrameos
Copy link
Contributor Author

Thrameos commented Sep 11, 2024 via email

@astrelsky
Copy link
Contributor

astrelsky commented Sep 11, 2024

Good to look into. I put in a patch that made JPype load as an Agent. That may allow us to get certain accesses that may otherwise be prohibited. The current issue with JPype is that we are side loading in a class loader post JVM startup. As an agent we can in theory change the byte code of anything started including permissions.

What accesses are you trying to make that would be prohibited? I just finished looking at the changes and didn't see any access that would be denied. I'm assuming there is no intent to support anything using the flawed SecurityManager API, since I think jpype would just not work entirely depending on configuration.

My initial concern with the java agent was that maybe I wouldn't be able to attach a profiler or debugger if I wanted. However, a quick Google search has shown me that you can specify multiple -javaagent so my concern is moot.

@Thrameos
Copy link
Contributor Author

Thrameos commented Sep 11, 2024 via email

@Thrameos
Copy link
Contributor Author

Thrameos commented Sep 12, 2024 via email

@astrelsky
Copy link
Contributor

astrelsky commented Sep 12, 2024

My solution was to call reflection and have it generate a stub class using ASM and interface using ASM. JPype implements those methods it wants on the interface portion and stub class forwards as needed. The hard part being that the interface needs to be able to also get ahold of the protected methods which would all be “_” leading members. We would then have to guard to make sure regular classes can’t access the underbar. One way to trick it would be to change “self” at the edge condition so that we had a public and private version of the wrapper class. When we call overridden methods we hand them the private one. I am just afraid the private ones would naturally get leaked if something returns self, or places itself on a list. The ASM pieces are very easy. It is proofing the rest.

For some reason I though ASM was GPL. Anyway just disregard that because it's not really important.

I had chosen to make things accessible through super(), which is where this idea comes from. What you could do is have a special _JSuperObject and/or _JSuperClass which would in place be used for the object instance and/or class when extending a java object. Since you know when someone is attempting to extend a java class, you can instead use the _JSuperClass which would have the protected methods/fields available.

I had used - instead of _ to guard things because the only way for you to get it would be through getattr. Outside of using getattr or reflection, in both Python and Java it would be interpreted as subtraction. Things will never be perfect. There will always be a way for someone to get at something they shouldn't. However, if they choose to go out of their way to get it, then they are free to shoot themselves in the foot.

@Thrameos
Copy link
Contributor Author

Thrameos commented Sep 12, 2024 via email

jpype/_core.py Fixed Show resolved Hide resolved
@Thrameos
Copy link
Contributor Author

@marscher I gave a shot at fixing collision between the two PR. Unfortunately, the bug regarding non-ASCII paths is a JVM problem and not really our issue. I find traffic on the Java forums going back in time and no good solutions. The solution in prior PR will break a number of behaviors because for many cases you absolutely MUST set the classpath when starting the JVM. Database services and such require it. I gave 3 hours trying to figure out what the encoding had done to the string from the os on CreateJavaVM which was causing an exception, but it is in a horrible spot for debugging. Barring recompiling the whole JVM with instrumentation I don't see how I can address it. The issue is that we properly encoded the vm arguments as UTF-8 when we pass it to Create_JavaVM, but the sun implementation of the URL encoder chokes causing a fail. My best solution was to pass ascii encoded arguments directly and then defer the others to late loading. But this just masks the problem as non-ascii paths are now second citizens and will work for some things and fail badly for others. Unfortunately none of this was the point of this PR, and my time is still very limited so this is the best I can do.

Will this need additional review or can I merge it at this point and start our release cycle?

@Thrameos
Copy link
Contributor Author

@marscher I don't understand the error in the build process and azure is not letting me in to view. I will have to cycle back to this next week as I have exhausted the available time.

Copy link

codecov bot commented Oct 19, 2024

Codecov Report

Attention: Patch coverage is 86.66667% with 2 lines in your changes missing coverage. Please review.

Project coverage is 87.15%. Comparing base (dc124d6) to head (b5cdd55).
Report is 17 commits behind head on master.

Files with missing lines Patch % Lines
jpype/_core.py 92.30% 1 Missing ⚠️
native/common/jp_classloader.cpp 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1182      +/-   ##
==========================================
- Coverage   87.20%   87.15%   -0.06%     
==========================================
  Files         113      113              
  Lines       10296    10267      -29     
  Branches     4076     4045      -31     
==========================================
- Hits         8979     8948      -31     
- Misses        722      726       +4     
+ Partials      595      593       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@Thrameos
Copy link
Contributor Author

Finally the tests are passing except for Python 3.13.

@marscher
Copy link
Member

@Thrameos Im sorry, that this mess eat up your time. The tests for Py313 are failing because the github token needed to download the Python version is not valid (anymore). I will give it a shot in another PR. So far we can merge this and start the release cycle.

Regarding the utf8 paths and jvm implementation (bugs) we should maybe just give a warning, that a path could not be considered and use the old behaviour instead of creating hard to find bugs due to second citizen treatment. What do you think?

@Thrameos
Copy link
Contributor Author

I dont think that the utf8 one is actually solvable. The original contibutor tried and ended up trying to load everything after startup. I tried and failed. I tested by setting another variable and then looking at resulting string type. The answer is that we are properly setting the encoding and there is nothing wrong with our string format. The problem is that during class loading it uses a defective url code that doesn't accept nonascii strings. Thus the only solution that the jvm supports is what i implemented here. (Ascii goes at load time, non ascii gets late load).

The only alternative is to completely replace the system class loader with our own which dodges the bad url parsing code. (But if then we have to watch is the user hasn't already done the same.) That is more work than I have bandwidth for. So I recommend the bandaid solution for thus version (2nd class is better than no class) then try a major fix next year to close the gap.

@astrelsky
Copy link
Contributor

The only alternative is to completely replace the system class loader with our own which dodges the bad url parsing code. (But if then we have to watch is the user hasn't already done the same.)

I can confirm I've already done the same. Ghidra sets the system class loader and uses the fact that it knows the system class loader class extensively (it checks during startup).

@Thrameos
Copy link
Contributor Author

@astrelsky would it make sense for you to try to make a PR what fixes the ascii issue with a system class loader replacement and test that we only do so when the user hasn't already done so? (Ie Ghidra)

The issue here being I am already overdue for a release. I am not sure if this is a big or small ask. We have a working DynamicClassLoader..
If it is easy to make it a real boy and replace with a few arguments then I could hold the release. Otherwise I plan to start the release scripts on Friday.

@astrelsky
Copy link
Contributor

@astrelsky would it make sense for you to try to make a PR what fixes the ascii issue with a system class loader replacement and test that we only do so when the user hasn't already done so? (Ie Ghidra)

The issue here being I am already overdue for a release. I am not sure if this is a big or small ask. We have a working DynamicClassLoader..
If it is easy to make it a real boy and replace with a few arguments then I could hold the release. Otherwise I plan to start the release scripts on Friday.

Sure can. I'll have a look tonight when I get off work. Just need to know what needs to be done in the system class loader that fixes the issue. I know ghidra has also had problems when users place it in a non ASCII path. I'm assuming no matter what the system class loader would need to be in an ASCII path? (not really a concern for jpype)

@Thrameos
Copy link
Contributor Author

Our Dynamic class loader does not have that restriction. So a URL class loader with a proper path to sources will work.

The problem is going to be bootstrapping; Our dynamic class loader works because it is using a full version of some classes (URI/URL) that only exist after the system class loader has loaded them. The one that sun used for initial loading is defective which is the source of the problem. That may mean that we have to implement some support class that is both ASCII and non-ASCII aware to get the process in motion.

The secondary issue is that our class loader currently assumes it is a secondary class loader. Thus it wants the real system classloader as the fallback. For a system class loader the bootloader is the backup. Of course if the user has given their own classloader we need to fall back to the current position.

There may be other requirements for a system class loader that I haven't researched. Unfortunately I have never had the need.

As far as testing I believe that we have everything we need. We test both ASCII and non-ASCII. Thus the only test we are missing is user specified system class loaders (making sure we don't override the users wish if they have replaced it.)

@astrelsky
Copy link
Contributor

astrelsky commented Oct 22, 2024

Our Dynamic class loader does not have that restriction. So a URL class loader with a proper path to sources will work.

The problem is going to be bootstrapping; Our dynamic class loader works because it is using a full version of some classes (URI/URL) that only exist after the system class loader has loaded them. The one that sun used for initial loading is defective which is the source of the problem. That may mean that we have to implement some support class that is both ASCII and non-ASCII aware to get the process in motion.

The secondary issue is that our class loader currently assumes it is a secondary class loader. Thus it wants the real system classloader as the fallback. For a system class loader the bootloader is the backup. Of course if the user has given their own classloader we need to fall back to the current position.

There may be other requirements for a system class loader that I haven't researched. Unfortunately I have never had the need.

As far as testing I believe that we have everything we need. We test both ASCII and non-ASCII. Thus the only test we are missing is user specified system class loaders (making sure we don't override the users wish if they have replaced it.)

Ok well this problem is infuriating considering it might be a 1 line fix in the jdk by using URLEncoder which has been in the jdk since 1.0 instead of using an incorrect implementation in sun.net.www.ParseUtil.
https://bugs.openjdk.org/browse/JDK-8079633?jql=text%20~%20%22ParseUtil%22

I haven't done anything more then attempt to understand the problem yet, which I'm pretty sure I do now. Unfortunately, I can think of a way to break it in every single case even if jpype has it's own system classloader that works. If someone sets up a virtualenv with a bad path, the jpype jar will be in a bad path and it won't load. I thought that maybe it could be copied to %TEMP% which may work for linux and mac, but for windows it contains the username which could contain characters that won't be encoded correctly.

Oh and yes, this bug is still present in jdk23...

@Thrameos
Copy link
Contributor Author

Yes, sadly this has to happen before our agent is loaded. If it was after the agent was loaded we can monkey patch the asm to change the loader to go to a different encoder. I understand how infuriating this is. I found issue running back for 15 years on the Java support pages (Sun and Oracle) meaning it would have been a small matter for someone to have fixed it. This really shouldn't be our issue. Barring hijacking the bootloader to replace the faulty code, we are mostly stuck with horrible work arounds.

@astrelsky
Copy link
Contributor

astrelsky commented Oct 22, 2024

Yes, sadly this has to happen before our agent is loaded. If it was after the agent was loaded we can monkey patch the asm to change the loader to go to a different encoder. I understand how infuriating this is. I found issue running back for 15 years on the Java support pages (Sun and Oracle) meaning it would have been a small matter for someone to have fixed it. This really shouldn't be our issue. Barring hijacking the bootloader to replace the faulty code, we are mostly stuck with horrible work arounds.

Implementing a tiny system class loader to be used to work around it should be trivial. I wouldn't even make any changes to the dynamic class loader and just add a new one. I think it would be best to only add it if there are any non ASCII characters in the path and there is no system class loader already set.

I'll try to have a fix in tomorrow night.

@marscher
Copy link
Member

Finally the tests are passing except for Python 3.13.

I figured, that the secret is not being passed on pull requests from forks. As you can see here, https://github.com/jpype-project/jpype/pull/1221/checks?check_run_id=31452501113 Python 3.13 gets downloaded. According to the Azure documentation one can enable the passing of the secret (which is of course not recommended), but there is no option in the gui, at least I didn't spot it (after search for half an hour...).

@Thrameos
Copy link
Contributor Author

@marscher How about we just set up a special run like release to test non-standard builds? Obviously that isn't as good as running the test cases for PR, but would allow us to build more complete testing before the release process. As only you or I will run it we can set up the proper tokens on jpype-project/jpype so we don't need to worry about forks. Just mirror the normal test script and add it to as a pipeline?

@astrelsky
Copy link
Contributor

astrelsky commented Oct 23, 2024

I probably should have asked before I started with the ascii issue but what branch did you want me to work off of?

I've already finished I think and am adding more tests.

@astrelsky
Copy link
Contributor

astrelsky commented Oct 23, 2024

I put it here for now just to stash it somewhere before I call it a night. Feel free to just cherry-pick it if that makes your lives easier.

astrelsky@4a2271b

There was one test case I couldn't figure out how to implement. It would require setting up a virtual environment placed in a non ascii path. This would cause the jpype jar to be in an unloadable path.

@Thrameos Thrameos closed this Oct 24, 2024
@Thrameos Thrameos reopened this Oct 24, 2024
@Thrameos
Copy link
Contributor Author

Merging for release

@Thrameos Thrameos merged commit 002c616 into jpype-project:master Oct 24, 2024
22 of 31 checks passed
@marscher
Copy link
Member

@marscher How about we just set up a special run like release to test non-standard builds? Obviously that isn't as good as running the test cases for PR, but would allow us to build more complete testing before the release process. As only you or I will run it we can set up the proper tokens on jpype-project/jpype so we don't need to worry about forks. Just mirror the normal test script and add it to as a pipeline?

That sounds like a sane approach - although I'd have prefered to run tests for upcoming Python versions for all PRs automatically.

@astrelsky
Copy link
Contributor

Well, I hate to be the bearer of bad news, but I found the first unintended consequence of the Java agent. I don't think it's too big of a deal though because any classloader being used as a system classloader will most likely have this, even if I forgot to add it.

test/jpypetest/test_startup.py::StartJVMCase::testASCIIPathWithSystemClassLoader [0.011s][warning][cds] Archived non-system classes are disabled because the java.system.class.loader property is specified (value = "jpype.startup.TestSystemClassLoader"). To use archived non-system classes, this property must not be set
System class loader does not define the appendToClassPathForInstrumentation method
Unable to add C:\Users\astre\Documents\jpype_tmp\org.jpype.jar to system class path - the system class loader does not define the appendToClassPathForInstrumentation methodFATAL ERROR in native method: processing of -javaagent failed, appending to system class path failed
 or the method failed
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [jvm.dll+0x6e8c69]  (no source info available)
V  [jvm.dll+0x3f3873]  (no source info available)
V  [jvm.dll+0x44485a]  (no source info available)
C  [instrument.dll+0x2772]  (no source info available)
V  [jvm.dll+0x5a713e]  (no source info available)
V  [jvm.dll+0x888b5d]  (no source info available)
V  [jvm.dll+0x45a16e]  (no source info available)
V  [jvm.dll+0x45bf81]  (no source info available)
C  [_jpype.cp313-win_amd64.pyd+0x11c83]  (no source info available)
C  [_jpype.cp313-win_amd64.pyd+0x41587]  (no source info available)
C  [python313.dll+0x3f62a]  cfunction_call+0x8e  (methodobject.c:551)
C  [python313.dll+0x86b93]  _PyObject_VectorcallTstate+0x693  (pycore_call.h:166)
C  [python313.dll+0x864f5]  PyObject_Vectorcall+0x35  (call.c:329)
C  [python313.dll+0x8bde6]  _PyEval_EvalFrameDefault+0x3be6  (generated_cases.c.h:817)
C  [python313.dll+0x872ec]  _PyFunction_Vectorcall+0x17c  (call.c:413)
C  [python313.dll+0x7e664]  method_vectorcall+0x314  (classobject.c:70)
C  [python313.dll+0x7df51]  _PyVectorcall_Call+0x49  (call.c:290)
C  [python313.dll+0x7de9b]  PyObject_Call+0x6f  (call.c:373)
C  [python313.dll+0x8de02]  _PyEval_EvalFrameDefault+0x5c02  (generated_cases.c.h:1355)
C  [python313.dll+0x330f4]  _PyEval_Vector+0x90  (ceval.c:1807)
C  [python313.dll+0x28ed5]  PyEval_EvalCode+0xad  (ceval.c:597)
C  [python313.dll+0x291d5]  run_eval_code_obj+0x71  (pythonrun.c:1324)
C  [python313.dll+0x292e0]  run_mod+0xcc  (pythonrun.c:1408)
C  [python313.dll+0x27985]  _PyRun_StringFlagsWithName+0x99  (pythonrun.c:1207)
C  [python313.dll+0x35cc]  _PyRun_SimpleStringFlagsWithName+0xcc  (pythonrun.c:548)
C  [python313.dll+0x383c]  pymain_run_command+0x9c  (main.c:253)
C  [python313.dll+0x4bc8]  pymain_run_python+0x1d8  (main.c:688)
C  [python313.dll+0x49c1]  Py_RunMain+0x15  (main.c:777)
C  [python313.dll+0x52e9]  Py_Main+0x25  (main.c:818)
C  [python.exe+0x1230]  __scrt_common_main_seh+0x10c  (exe_common.inl:288)
C  [KERNEL32.DLL+0x1257d]  (no source info available)
C  [ntdll.dll+0x5af08]  (no source info available)

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.

Clarity in Implementation of interfaces with default methods
3 participants