[not part of build] Added pending exception support, to deal with problem of not being able to enter monitors with a pending exception in the JNIEnv.

This commit is contained in:
beard%netscape.com 2001-11-02 08:11:37 +00:00
Родитель 0b905e50bf
Коммит cab988a630
2 изменённых файлов: 97 добавлений и 52 удалений

Просмотреть файл

@ -152,6 +152,7 @@ static void netscape_oji_JNIThread_run(JNIEnv* env, jobject self)
JavaMessage* msg = requests.getMessage(); JavaMessage* msg = requests.getMessage();
if (msg != NULL) { if (msg != NULL) {
msg->execute(env); msg->execute(env);
secureEnv->savePendingException(env);
replies.putMessage(msg); replies.putMessage(msg);
replies.notify(); replies.notify();
} else { } else {
@ -354,7 +355,7 @@ CSecureEnv::CSecureEnv(MRJPlugin* plugin, JNIEnv* proxyEnv, JNIEnv* javaEnv)
: SupportsMixin(this, sInterfaces, kInterfaceCount), : SupportsMixin(this, sInterfaces, kInterfaceCount),
mPlugin(plugin), mProxyEnv(proxyEnv), mJavaEnv(javaEnv), mPlugin(plugin), mProxyEnv(proxyEnv), mJavaEnv(javaEnv),
mSession(plugin->getSession()), mThreadManager(plugin->getThreadManager()), mSession(plugin->getSession()), mThreadManager(plugin->getThreadManager()),
mIsRunning(NULL), mJavaQueue(NULL), mNativeQueue(NULL) mIsRunning(NULL), mJavaQueue(NULL), mNativeQueue(NULL), mPendingException(NULL)
{ {
// need to create the JNIThread for communicating with Java. // need to create the JNIThread for communicating with Java.
if (mJavaEnv != NULL) if (mJavaEnv != NULL)
@ -1451,16 +1452,18 @@ NS_IMETHODIMP CSecureEnv::ThrowNew(/*[in]*/ jclass clazz,
class ExceptionOccurredMessage : public JavaMessage { class ExceptionOccurredMessage : public JavaMessage {
CSecureEnv* secureEnv;
jthrowable* result; jthrowable* result;
public: public:
ExceptionOccurredMessage(jthrowable* result) ExceptionOccurredMessage(CSecureEnv* secureEnv, jthrowable* result)
{ {
this->secureEnv = secureEnv;
this->result = result; this->result = result;
} }
virtual void execute(JNIEnv* env) virtual void execute(JNIEnv* env)
{ {
*result = env->ExceptionOccurred(); *result = secureEnv->getPendingException(env);
} }
}; };
@ -1470,7 +1473,7 @@ NS_IMETHODIMP CSecureEnv::ExceptionOccurred(/*[out]*/ jthrowable* result)
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
#if PROXY_JNI_CALLS #if PROXY_JNI_CALLS
ExceptionOccurredMessage msg(result); ExceptionOccurredMessage msg(this, result);
sendMessageToJava(&msg); sendMessageToJava(&msg);
#else #else
*result = mJavaEnv->ExceptionOccurred(); *result = mJavaEnv->ExceptionOccurred();
@ -1497,14 +1500,20 @@ NS_IMETHODIMP CSecureEnv::ExceptionDescribe(void)
return NS_OK; return NS_OK;
} }
class ExceptionClearMessage : public JavaMessage {
CSecureEnv* secureEnv;
public:
ExceptionClearMessage(CSecureEnv* secureEnv)
{
this->secureEnv = secureEnv;
}
virtual void execute(JNIEnv* env) { secureEnv->clearPendingException(env); }
};
NS_IMETHODIMP CSecureEnv::ExceptionClear(void) NS_IMETHODIMP CSecureEnv::ExceptionClear(void)
{ {
#if PROXY_JNI_CALLS #if PROXY_JNI_CALLS
class ExceptionClearMessage : public JavaMessage { ExceptionClearMessage msg(this);
public:
virtual void execute(JNIEnv* env) { env->ExceptionClear(); }
} msg;
sendMessageToJava(&msg); sendMessageToJava(&msg);
#else #else
mJavaEnv->ExceptionClear(); mJavaEnv->ExceptionClear();
@ -2920,6 +2929,36 @@ void CSecureEnv::messageLoop(JNIEnv* env, JavaMessage* msg, JavaMessageQueue* se
} }
} }
void CSecureEnv::savePendingException(JNIEnv* env)
{
// first off, always restore the env to a known state.
jthrowable pendingException = env->ExceptionOccurred();
env->ExceptionClear();
if (mPendingException)
env->DeleteGlobalRef(mPendingException);
if (pendingException) {
mPendingException = (jthrowable) env->NewGlobalRef(pendingException);
env->DeleteLocalRef(pendingException);
}
}
jthrowable CSecureEnv::getPendingException(JNIEnv* env)
{
if (mPendingException)
return (jthrowable) env->NewLocalRef(mPendingException);
return NULL;
}
void CSecureEnv::clearPendingException(JNIEnv* env)
{
if (mPendingException) {
env->DeleteGlobalRef(mPendingException);
mPendingException = NULL;
}
}
CSecureEnv* GetSecureJNI(JNIEnv* env, jobject thread) CSecureEnv* GetSecureJNI(JNIEnv* env, jobject thread)
{ {
CSecureEnv* secureJNI = NULL; CSecureEnv* secureJNI = NULL;

Просмотреть файл

@ -35,9 +35,9 @@
* ----- END LICENSE BLOCK ----- */ * ----- END LICENSE BLOCK ----- */
/* /*
CSecureEnv.h CSecureEnv.h
Rewritten for use with MRJ plugin by Patrick C. Beard. Rewritten for use with MRJ plugin by Patrick C. Beard.
*/ */
#ifndef CSecureJNI2_h___ #ifndef CSecureJNI2_h___
@ -61,7 +61,7 @@ class CSecureEnv : public nsISecureEnv, public nsIRunnable, private SupportsMixi
public: public:
DECL_SUPPORTS_MIXIN DECL_SUPPORTS_MIXIN
static NS_METHOD Create(MRJPlugin* plugin, JNIEnv* proxyEnv, const nsIID& aIID, void* *aInstancePtr); static NS_METHOD Create(MRJPlugin* plugin, JNIEnv* proxyEnv, const nsIID& aIID, void* *aInstancePtr);
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// from nsISecureJNI2: // from nsISecureJNI2:
@ -302,7 +302,7 @@ public:
/*[out]*/ jsize* result); /*[out]*/ jsize* result);
NS_IMETHOD NewObjectArray(/*[in]*/ jsize len, NS_IMETHOD NewObjectArray(/*[in]*/ jsize len,
/*[in]*/ jclass clazz, /*[in]*/ jclass clazz,
/*[in]*/ jobject init, /*[in]*/ jobject init,
/*[out]*/ jobjectArray* result); /*[out]*/ jobjectArray* result);
@ -365,49 +365,55 @@ public:
CSecureEnv(MRJPlugin* plugin, JNIEnv* proxyEnv, JNIEnv* javaEnv = NULL); CSecureEnv(MRJPlugin* plugin, JNIEnv* proxyEnv, JNIEnv* javaEnv = NULL);
virtual ~CSecureEnv(void); virtual ~CSecureEnv(void);
/** /**
* Called by the native run method, to connect the * Called by the native run method, to connect the
* thread and the secure env. * thread and the secure env.
*/ */
void initialize(JNIEnv* javaEnv, jboolean* isRunning, JavaMessageQueue* javaQueue, JavaMessageQueue* nativeQueue); void initialize(JNIEnv* javaEnv, jboolean* isRunning, JavaMessageQueue* javaQueue, JavaMessageQueue* nativeQueue);
jboolean isInitialized() { return mJavaQueue != NULL; } jboolean isInitialized() { return mJavaQueue != NULL; }
void setProxyEnv(JNIEnv* proxyEnv) { mProxyEnv = proxyEnv; } void setProxyEnv(JNIEnv* proxyEnv) { mProxyEnv = proxyEnv; }
JNIEnv* getProxyEnv() { return mProxyEnv; } JNIEnv* getProxyEnv() { return mProxyEnv; }
void setJavaEnv(JNIEnv* javaEnv) { mJavaEnv = javaEnv; } void setJavaEnv(JNIEnv* javaEnv) { mJavaEnv = javaEnv; }
JNIEnv* getJavaEnv() { return mJavaEnv; } JNIEnv* getJavaEnv() { return mJavaEnv; }
MRJSession* getSession() { return mSession; } MRJSession* getSession() { return mSession; }
nsIThreadManager* getThreadManager() { return mThreadManager; } nsIThreadManager* getThreadManager() { return mThreadManager; }
void getMessageQueues(JavaMessageQueue*& javaQueue, JavaMessageQueue*& nativeQueue) void getMessageQueues(JavaMessageQueue*& javaQueue, JavaMessageQueue*& nativeQueue)
{ {
javaQueue = mJavaQueue; javaQueue = mJavaQueue;
nativeQueue = mNativeQueue; nativeQueue = mNativeQueue;
} }
void sendMessageToJava(JavaMessage* msg); void sendMessageToJava(JavaMessage* msg);
void sendMessageFromJava(JNIEnv* javaEnv, JavaMessage* msg, Boolean busyWaiting = false); void sendMessageFromJava(JNIEnv* javaEnv, JavaMessage* msg, Boolean busyWaiting = false);
void messageLoop(JNIEnv* env, JavaMessage* msgToSend, JavaMessageQueue* sendQueue, JavaMessageQueue* receiveQueue, Boolean busyWaiting = false); void messageLoop(JNIEnv* env, JavaMessage* msgToSend, JavaMessageQueue* sendQueue, JavaMessageQueue* receiveQueue, Boolean busyWaiting = false);
void savePendingException(JNIEnv* env);
jthrowable getPendingException(JNIEnv* env);
void clearPendingException(JNIEnv* env);
protected: protected:
MRJPlugin* mPlugin; MRJPlugin* mPlugin;
JNIEnv* mProxyEnv; JNIEnv* mProxyEnv;
MRJSession* mSession; MRJSession* mSession;
nsIThreadManager* mThreadManager; nsIThreadManager* mThreadManager;
JNIEnv* mJavaEnv; JNIEnv* mJavaEnv;
jboolean* mIsRunning; jboolean* mIsRunning;
JavaMessageQueue* mJavaQueue; JavaMessageQueue* mJavaQueue;
JavaMessageQueue* mNativeQueue; JavaMessageQueue* mNativeQueue;
jthrowable mPendingException;
private: private:
// support for SupportsMixin. // support for SupportsMixin.
static const InterfaceInfo sInterfaces[]; static const InterfaceInfo sInterfaces[];
static const UInt32 kInterfaceCount; static const UInt32 kInterfaceCount;
}; };
/** /**