Tag: cws_src680_sb36 User: sb Date: 2007/03/05 08:52:57 Modified: dba/connectivity/source/drivers/jdbc/JConnection.cxx
Log: #i69624# Load each class only once. File Changes: Directory: /dba/connectivity/source/drivers/jdbc/ ================================================= File [changed]: JConnection.cxx Url: http://dba.openoffice.org/source/browse/dba/connectivity/source/drivers/jdbc/JConnection.cxx?r1=1.2.28.2&r2=1.2.28.3 Delta lines: +111 -4 --------------------- --- JConnection.cxx 22 Jan 2007 08:54:09 -0000 1.2.28.2 +++ JConnection.cxx 5 Mar 2007 16:52:53 -0000 1.2.28.3 @@ -4,9 +4,9 @@ * * $RCSfile: JConnection.cxx,v $ * - * $Revision: 1.2.28.2 $ + * $Revision: 1.2.28.3 $ * - * last change: $Author: sb $ $Date: 2007/01/22 08:54:09 $ + * last change: $Author: sb $ $Date: 2007/03/05 16:52:53 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -72,6 +72,10 @@ #include "java/util/Property.hxx" #include "com/sun/star/uno/XComponentContext.hpp" #include "jvmaccess/classpath.hxx" + +#include <jni.h> + +#include <list> #include <memory> using namespace connectivity; @@ -82,6 +86,109 @@ using namespace ::com::sun::star::container; using namespace ::com::sun::star::lang; +namespace { + +struct JObject { + JObject(JNIEnv * environment): object(NULL), m_environment(environment) {} + ~JObject() { if (object != NULL) m_environment->DeleteLocalRef(object); } + + jobject release() { + jobject t = object; + object = NULL; + return t; + } + + jobject object; + +private: + JNIEnv *& m_environment; +}; + +struct ClassMapEntry { + ClassMapEntry( + rtl::OUString const & theClassPath, rtl::OUString const & theClassName): + classPath(theClassPath), className(theClassName), classObject(NULL) {} + + rtl::OUString classPath; + rtl::OUString className; + jweak classObject; +}; + +typedef std::list< ClassMapEntry > ClassMap; + +struct ClassMapData { + osl::Mutex mutex; + + ClassMap map; +}; + +struct ClassMapDataInit { + ClassMapData * operator()() { + static ClassMapData instance; + return &instance; + } +}; + +// Load a class (see jvmaccess::ClassPath::loadClass in jvmaccess/classpath.hxx +// for details). A map from (classPath, name) pairs to weak Java class +// references is maintained, so that a class is only loaded once. If null is +// returned, a (still pending) JNI exception occurred. +jclass loadClass( + Reference< XComponentContext > const & context, JNIEnv * environment, + rtl::OUString const & classPath, rtl::OUString const & name) +{ + // For any jweak entries still present in the map upon destruction, + // DeleteWeakGlobalRef is not called (which is a leak): + ClassMapData * d = + rtl_Instance< ClassMapData, ClassMapDataInit, osl::MutexGuard, + osl::GetGlobalMutex >::create( + ClassMapDataInit(), osl::GetGlobalMutex()); + osl::MutexGuard g(d->mutex); + JObject cl(environment); + // Prune dangling weak references from the list while searching for a match, + // so that the list cannot grow unbounded: + for (ClassMap::iterator i(d->map.begin()); i != d->map.end();) { + JObject o(environment); + o.object = environment->NewLocalRef(i->classObject); + if (o.object == NULL) { + if (environment->ExceptionCheck()) { + return NULL; + } + if (i->classObject != NULL) { + environment->DeleteWeakGlobalRef(i->classObject); + } + i = d->map.erase(i); + } else { + if (i->classPath == classPath && i->className == name) { + cl.object = o.release(); + } + ++i; + } + } + if (cl.object == NULL) { + // Push a new ClassMapEntry (which can potentially fail) before loading + // the class, so that it never happens that a class is loaded but not + // added to the map (which could have effects on the JVM that are not + // easily undone). If the pushed ClassMapEntry is not used after all + // (jvmaccess::ClassPath::loadClass throws, return NULL, etc.) it will + // be pruned on next call because its classObject is null: + d->map.push_front(ClassMapEntry(classPath, name)); + cl.object = jvmaccess::ClassPath::loadClass( + context, environment, classPath, name); + if (cl.object == NULL) { + return NULL; + } + jweak w = environment->NewWeakGlobalRef(cl.object); + if (w == NULL) { + return NULL; + } + d->map.front().classObject = w; + } + return static_cast< jclass >(cl.release()); +} + +} + //------------------------------------------------------------------------------ IMPLEMENT_SERVICE_INFO(java_sql_Connection,"com.sun.star.sdbcx.JConnection","com.sun.star.sdbc.Connection"); //------------------------------------------------------------------------------ @@ -748,7 +855,7 @@ pDrvClass.reset( new java_lang_Class( t.pEnv, - jvmaccess::ClassPath::loadClass( + loadClass( Reference< XComponentContext >( Reference< XPropertySet >( m_pDriver->getORB(), --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
