Skip to content

Commit

Permalink
Merge branch 'master' into android
Browse files Browse the repository at this point in the history
  • Loading branch information
marscher committed Sep 3, 2020
2 parents f6dfe61 + 976856c commit b7f2989
Show file tree
Hide file tree
Showing 24 changed files with 299 additions and 213 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 1.0.2_dev0
current_version = 1.0.3_dev0
commit = True
tag = False
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\_(?P<release>[a-z]+)(?P<build>\d+))?
Expand Down
42 changes: 41 additions & 1 deletion doc/CHANGELOG.rst
Expand Up @@ -4,7 +4,29 @@ Changelog
This changelog *only* contains changes from the *first* pypi release (0.5.4.3) onwards.

Latest Changes:
- **1.0.2_dev0 - 2020-07-16**

- **1.0.3_dev0 - unreleased**

- Fixed crash when manually creating wrappers for anonymous classes.

- Fixed reference count problem in stackframes used for exceptions.

- Errors report `*static*` when the matching with a static method
so that it is clear when a member method was called statically.

- java.lang.String slices function like Python string slice.

- Java packages now operate as normal Python modules. Removed restrictions
regarding setattr. All package instances for the same package name are
shared so that functionality added to one instance is shared wiht all
instances.

- **1.0.2 - 2020-07-27**

- The wrapper for Throwable was getting the wrapper for Object rather than
the expected wrapper resulting in odd conversions from Python classes.

- Typos within the import system resulting in "jname" not found corrected.

- ^C propogates to a KeyboardInterrupt properly.

Expand All @@ -21,6 +43,24 @@ Latest Changes:
- Corrected symbol problem with Python 3.5.3. PySlice_Unpack was introduced
in a later patch release and should not have been used.

- **shutdown** The behavior log entry for changes on shutdown were lost in
the 1.0 release. JPype now calls the JVM shutdown routine which tries to
gracefully exit when shutdown is called. This results in several changes
in behavior. Non daemon threads can now hold open the JVM until they have
completed. Proxy calls will hold the shutdown until the call is completed
but will receive an interrupt message. Files now close properly and will
flush if the threads properly handle the exception. Resource clean up
hooks and finalizers are executed. AtExit hooks in the JVM are called as
spawned threads. Automatic attachment of threads by use of the JVM from
Python are done as daemon but can be reattached as user threads on demand.
Buggy code that fails to properly handle thread clean up will likely hang
on shutdown. Additional documentation is located in the user guide.

- A bug was reported with numpy.linalg.inv resulting in crashes. This was
traced to an interaction with threading between the JVM and some compilations
of numpy. The workaround appears to be calling numpy.linalg.inv prior to
starting the JVM.

- **1.0.1 - 2020-07-16**

- Workarounds for Python 3.8.4 release. Python altered logic regarding the
Expand Down
2 changes: 1 addition & 1 deletion doc/release.rst
Expand Up @@ -24,9 +24,9 @@ Full process:
``git checkout -b releases/{version}``
- [ ] Merge the current master with the release
``git pull origin master``
- [ ] Edit doc/CHANGELOG.rst
- [ ] Start a release
``bumpversion release``
- [ ] Edit doc/CHANGELOG.rst
- [ ] Send the release to be evaluated
``git push``
- [ ] Verify CI on azure
Expand Down
2 changes: 1 addition & 1 deletion jpype/__init__.py
Expand Up @@ -51,7 +51,7 @@
__all__.extend(_jcustomizer.__all__)
__all__.extend(_gui.__all__)

__version__ = "1.0.2_dev0"
__version__ = "1.0.3_dev0"
__version_info__ = __version__.split('.')


Expand Down
3 changes: 3 additions & 0 deletions jpype/_jstring.py
Expand Up @@ -45,6 +45,9 @@ def __len__(self):
return self.length()

def __getitem__(self, i):
if isinstance(i, slice):
return str(self)[i]

if i < 0:
i += len(self)
if i < 0:
Expand Down
6 changes: 3 additions & 3 deletions jpype/protocol.py
Expand Up @@ -66,9 +66,9 @@ def _JPathConvert(jcls, obj):
def _JFileConvert(jcls, obj):
return jcls(obj.__fspath__())


@_jcustomizer.JConversion("java.util.Collection", instanceof=Sequence,
excludes=str)
# To be added in 1.1.x
#@_jcustomizer.JConversion("java.util.Iterable", instanceof=Sequence, excludes=str)
@_jcustomizer.JConversion("java.util.Collection", instanceof=Sequence, excludes=str)
def _JSequenceConvert(jcls, obj):
return _jclass.JClass('java.util.Arrays').asList(obj)

Expand Down
4 changes: 4 additions & 0 deletions native/common/include/jp_context.h
Expand Up @@ -16,6 +16,7 @@
#ifndef JP_CONTEXT_H
#define JP_CONTEXT_H
#include <jpype.h>
#include <list>

/** JPClass is a bit heavy when we just need to hold a
* class reference. It causes issues during bootstrap. Thus we
Expand Down Expand Up @@ -260,6 +261,9 @@ class JPContext
bool m_Embedded;
public:
JPGarbageCollection *m_GC;

// This will gather C++ resources to clean up after shutdown.
std::list<JPResource*> m_Resources;
} ;

extern void JPRef_failed();
Expand Down
2 changes: 2 additions & 0 deletions native/common/jp_boxedtype.cpp
Expand Up @@ -84,13 +84,15 @@ JPMatch::Type JPBoxedType::findJavaConversion(JPMatch &match)

void JPBoxedType::getConversionInfo(JPConversionInfo &info)
{
JP_TRACE_IN("JPBoxedType::getConversionInfo");
JPJavaFrame frame = JPJavaFrame::outer(m_Context);
m_PrimitiveType->getConversionInfo(info);
JPPyObject::call(PyObject_CallMethod(info.expl, "extend", "O", info.implicit));
JPPyObject::call(PyObject_CallMethod(info.implicit, "clear", ""));
JPPyObject::call(PyObject_CallMethod(info.implicit, "extend", "O", info.exact));
JPPyObject::call(PyObject_CallMethod(info.exact, "clear", ""));
JPClass::getConversionInfo(info);
JP_TRACE_OUT;
}

jobject JPBoxedType::box(JPJavaFrame &frame, jvalue v)
Expand Down
2 changes: 2 additions & 0 deletions native/common/jp_class.cpp
Expand Up @@ -416,10 +416,12 @@ JPMatch::Type JPClass::findJavaConversion(JPMatch &match)

void JPClass::getConversionInfo(JPConversionInfo &info)
{
JP_TRACE_IN("JPClass::getConversionInfo");
JPJavaFrame frame = JPJavaFrame::outer(m_Context);
objectConversion->getInfo(this, info);
hintsConversion->getInfo(this, info);
PyList_Append(info.ret, PyJPClass_create(frame, this).get());
JP_TRACE_OUT;
}


Expand Down
8 changes: 8 additions & 0 deletions native/common/jp_context.cpp
Expand Up @@ -386,6 +386,14 @@ void JPContext::shutdownJVM()
m_JavaVM->DestroyJavaVM();
}

JP_TRACE("Delete resources");
for (std::list<JPResource*>::iterator iter = m_Resources.begin();
iter != m_Resources.end(); ++iter)
{
delete *iter;
}
m_Resources.clear();

// unload the jvm library
JP_TRACE("Unload JVM");
m_JavaVM = NULL;
Expand Down
3 changes: 3 additions & 0 deletions native/common/jp_exception.cpp
Expand Up @@ -490,7 +490,10 @@ PyTracebackObject *tb_create(
PyFrameObject *frame = (PyFrameObject*) PyFrame_Type.tp_alloc(&PyFrame_Type, 0);
frame->f_back = NULL;
if (last_traceback != NULL)
{
frame->f_back = last_traceback->tb_frame;
Py_INCREF(frame->f_back);
}
frame->f_builtins = dict;
Py_INCREF(frame->f_builtins);
frame->f_code = (PyCodeObject*) code;
Expand Down
7 changes: 6 additions & 1 deletion native/common/jp_methoddispatch.cpp
Expand Up @@ -159,7 +159,12 @@ bool JPMethodDispatch::findOverload(JPJavaFrame& frame, JPMethodMatch &bestMatch
if (JPModifier::isConstructor(m_Modifiers))
ss << "No matching overloads found for constructor " << m_Class->getCanonicalName() << "(";
else
ss << "No matching overloads found for " << m_Class->getCanonicalName() << "." << getName() << "(";
{
ss << "No matching overloads found for ";
if (!callInstance)
ss << "*static* ";
ss << m_Class->getCanonicalName() << "." << getName() << "(";
}
size_t start = callInstance ? 1 : 0;
for (size_t i = start; i < arg.size(); ++i)
{
Expand Down
2 changes: 2 additions & 0 deletions native/common/jp_numbertype.cpp
Expand Up @@ -48,10 +48,12 @@ JPMatch::Type JPNumberType::findJavaConversion(JPMatch& match)

void JPNumberType::getConversionInfo(JPConversionInfo &info)
{
JP_TRACE_IN("JPNumberType::getConversionInfo");
JPJavaFrame frame = JPJavaFrame::outer(m_Context);
javaNumberAnyConversion->getInfo(this, info);
boxLongConversion->getInfo(this, info);
boxDoubleConversion->getInfo(this, info);
hintsConversion->getInfo(this, info);
PyList_Append(info.ret, PyJPClass_create(frame, this).get());
JP_TRACE_OUT;
}
2 changes: 2 additions & 0 deletions native/common/jp_objecttype.cpp
Expand Up @@ -52,6 +52,7 @@ JPMatch::Type JPObjectType::findJavaConversion(JPMatch& match)

void JPObjectType::getConversionInfo(JPConversionInfo &info)
{
JP_TRACE_IN("JPObjectType::getConversionInfo");
JPJavaFrame frame = JPJavaFrame::outer(m_Context);
nullConversion->getInfo(this, info);
objectConversion->getInfo(this, info);
Expand All @@ -63,4 +64,5 @@ void JPObjectType::getConversionInfo(JPConversionInfo &info)
proxyConversion->getInfo(this, info);
hintsConversion->getInfo(this, info);
PyList_Append(info.ret, PyJPClass_create(frame, this).get());
JP_TRACE_OUT;
}
4 changes: 2 additions & 2 deletions native/common/jp_typefactory.cpp
Expand Up @@ -113,7 +113,7 @@ JNIEXPORT void JNICALL Java_org_jpype_manager_TypeFactoryNative_destroy(
jlong* values = accessor.get();
for (int i = 0; i < sz; ++i)
{
delete (JPResource*) values[i];
context->m_Resources.push_back((JPResource*) values[i]);
}
return;
JP_JAVA_CATCH(); // GCOVR_EXCL_LINE
Expand Down Expand Up @@ -205,7 +205,7 @@ JNIEXPORT jlong JNICALL Java_org_jpype_manager_TypeFactoryNative_defineObjectCla
(JPClass*) superClass, interfaces, modifiers));
if (className == "java.lang.Throwable")
return (jlong) (context->_java_lang_Throwable
= new JPObjectType(frame, cls, className,
= new JPClassType(frame, cls, className,
(JPClass*) superClass, interfaces, modifiers));

if (className == "java.lang.Number")
Expand Down
39 changes: 19 additions & 20 deletions native/java/org/jpype/JPypeContext.java
Expand Up @@ -69,7 +69,7 @@
public class JPypeContext
{

public final String VERSION = "1.0.2_dev0";
public final String VERSION = "1.0.3_dev0";

private static JPypeContext INSTANCE = new JPypeContext();
// This is the C++ portion of the context.
Expand All @@ -78,7 +78,6 @@ public class JPypeContext
private TypeManager typeManager;
private DynamicClassLoader classLoader;
private final AtomicInteger shutdownFlag = new AtomicInteger();
private final AtomicInteger proxyCount = new AtomicInteger();
private final List<Thread> shutdownHooks = new ArrayList<>();
private final List<Runnable> postHooks = new ArrayList<>();

Expand Down Expand Up @@ -208,15 +207,15 @@ private void shutdown()

// Wait for any unregistered proxies to finish so that we don't yank
// the rug out from under them result in a segfault.
while (this.proxyCount.get() > 0)
{
try
{
Thread.sleep(10);
} catch (InterruptedException ex)
{
}
}
// while (this.proxyCount.get() > 0)
// {
// try
// {
// Thread.sleep(10);
// } catch (InterruptedException ex)
// {
// }
// }

// // Check to see if who is alive
// threads = Thread.getAllStackTraces();
Expand Down Expand Up @@ -452,15 +451,15 @@ public boolean isShutdown()
return shutdownFlag.get() > 0;
}

public void incrementProxy()
{
proxyCount.incrementAndGet();
}

public void decrementProxy()
{
proxyCount.decrementAndGet();
}
// public void incrementProxy()
// {
// proxyCount.incrementAndGet();
// }
//
// public void decrementProxy()
// {
// proxyCount.decrementAndGet();
// }

public long getExcClass(Throwable th)
{
Expand Down
2 changes: 2 additions & 0 deletions native/java/org/jpype/manager/TypeManager.java
Expand Up @@ -445,6 +445,8 @@ private ClassDescriptor createOrdinaryClass(Class<?> cls, boolean special, boole

// FIXME watch out for anonyous and lambda here.
String name = cls.getCanonicalName();
if (name == null)
name = cls.getName();

// Create the JPClass
long classPtr = typeFactory.defineObjectClass(context, cls, name,
Expand Down
4 changes: 2 additions & 2 deletions native/java/org/jpype/proxy/JPypeProxy.java
Expand Up @@ -71,7 +71,7 @@ public Object invoke(Object proxy, Method method, Object[] args)
{
try
{
context.incrementProxy();
// context.incrementProxy();
if (context.isShutdown())
throw new RuntimeException("Proxy called during shutdown");

Expand All @@ -94,7 +94,7 @@ public Object invoke(Object proxy, Method method, Object[] args)
return hostInvoke(context.getContext(), method.getName(), instance, returnType, parameterTypes, args);
} finally
{
context.decrementProxy();
// context.decrementProxy();
}
}

Expand Down
2 changes: 1 addition & 1 deletion native/python/pyjp_module.cpp
Expand Up @@ -711,7 +711,7 @@ PyMODINIT_FUNC PyInit__jpype()
// PyJPModule = module;
Py_INCREF(module);
PyJPModule = module;
PyModule_AddStringConstant(module, "__version__", "1.0.2_dev0");
PyModule_AddStringConstant(module, "__version__", "1.0.3_dev0");

// Initialize each of the python extension types
PyJPClass_initType(module);
Expand Down

0 comments on commit b7f2989

Please sign in to comment.