Skip to content

Commit

Permalink
[connection]完善数据库驱动类加载器,避免驱动本身的资源、类代理至父类加载器加载
Browse files Browse the repository at this point in the history
  • Loading branch information
datageartech committed Mar 10, 2020
1 parent f1d37ab commit a9b0294
Showing 1 changed file with 108 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@
/**
* 指定路径的驱动类加载器。
* <p>
* 注意:此类会优先从指定路径中加载类,因此,不应该将标准库放入此路径中。
* 注意:对于非JDK自带的类,此类加载器仅会从{@linkplain #getPath()}加载,而不会代理给父类加载器。
* </p>
* <p>
* 此规则可以避免驱动类依赖的某些库在{@linkplain #getPath()}中找不到时代理至应用类加载器,而可能出现版本不一致的情况。
* </p>
*
* @author [email protected]
Expand Down Expand Up @@ -83,85 +86,89 @@ public void setOutsideForceLoads(Set<String> outsideForceLoads)
@Override
public URL getResource(String name)
{
if (LOGGER.isDebugEnabled())
LOGGER.debug("start getting resource URL for [" + name + "]");

URL url = findResource(name);

if (url == null)
{
ClassLoader parent = getParentClassLoader();

if (LOGGER.isDebugEnabled())
LOGGER.debug("delegate parent class loader for getting resource URL for [" + name + "]");

return parent.getResource(name);
}
// 对于独立的驱动程序类加载器,不应该代理至父类加载器
// if (url == null)
// {
// ClassLoader parent = getParentClassLoader();
//
// if (LOGGER.isDebugEnabled())
// LOGGER.debug("delegate parent class loader for getting resource URL for [" + name + "]");
//
// return parent.getResource(name);
// }

if (LOGGER.isDebugEnabled())
LOGGER.debug("got resource URL [" + url + "] for [" + name + "] in path [" + getPath() + "]");
LOGGER.debug("getResource [" + url + "] for [" + name + "] in path [" + getPath() + "]");

return url;
}

@Override
public Enumeration<URL> getResources(String name) throws IOException
{
if (LOGGER.isDebugEnabled())
LOGGER.debug("start getting resource URLs for [" + name + "]");

Enumeration<URL> urls = findResources(name);

if (urls == null || urls.hasMoreElements())
{
ClassLoader parent = getParentClassLoader();

if (LOGGER.isDebugEnabled())
LOGGER.debug("delegate parent class loader for getting resource URLs for [" + name + "]");

return parent.getResources(name);
}
// 对于独立的驱动程序类加载器,不应该代理至父类加载器
// if (urls == null || urls.hasMoreElements())
// {
// ClassLoader parent = getParentClassLoader();
//
// if (LOGGER.isDebugEnabled())
// LOGGER.debug("delegate parent class loader for getting resource URLs for [" + name + "]");
//
// return parent.getResources(name);
// }

if (LOGGER.isDebugEnabled())
LOGGER.debug("got resource URLs for [" + name + "] in path [" + getPath() + "]");
LOGGER.debug("getResources for [" + name + "] in path [" + getPath() + "]");

return urls;
}

@Override
public InputStream getResourceAsStream(String name)
{
if (LOGGER.isDebugEnabled())
LOGGER.debug("start getting resource as stream for [" + name + "]");

URL url = findResource(name);

if (url == null)
{
ClassLoader parent = getParentClassLoader();
// 对于独立的驱动程序类加载器,不应该代理至父类加载器
// if (url == null)
// {
// ClassLoader parent = getParentClassLoader();
//
// if (LOGGER.isDebugEnabled())
// LOGGER.debug("delegate parent class loader for getting resource as stream for [" + name + "]");
//
// return parent.getResourceAsStream(name);
// }

if (LOGGER.isDebugEnabled())
LOGGER.debug("delegate parent class loader for getting resource as stream for [" + name + "]");
if (url == null)
return null;

return parent.getResourceAsStream(name);
}
InputStream in = null;

try
{
return url.openStream();
in = url.openStream();
}
catch (IOException e)
{
return null;
}

if (LOGGER.isDebugEnabled())
LOGGER.debug("getResourceAsStream [" + in + "] for [" + name + "] in path [" + getPath() + "]");

return in;
}

@Override
protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException, ClassFormatError
{
if (LOGGER.isDebugEnabled())
LOGGER.debug("start loading class [" + name + "]");
// JDK标准库应由父类加载
if (isJDKStandardClassName(name))
return Class.forName(name, resolve, getParentClassLoader());

// -拷贝自java.net.URLClassLoader.FactoryURLClassLoader
SecurityManager sm = System.getSecurityManager();
Expand All @@ -179,57 +186,48 @@ protected synchronized Class<?> loadClass(String name, boolean resolve)

if (clazz == null)
{
// 标准库不应在此加载
if (name.startsWith("java"))
;
else
try
{
clazz = findClass(name);
}
catch(ClassNotFoundException e)
{
}
catch(ClassFormatError e)
{
try
{
clazz = findClass(name);
}
catch (ClassNotFoundException e)
{
// 找不到类,则代理给父类加载器
}
catch (ClassFormatError e)
{
// 类加载出错(比如版本不兼容),则抛出
throw e;
}
// 类加载出错(比如版本不兼容),则抛出
throw e;
}
}

if (clazz == null)
// 强制在此加载的类
if (clazz == null && this.outsideForceLoads != null && this.outsideForceLoads.contains(name))
{
// 强制在此加载的类
if (this.outsideForceLoads != null && this.outsideForceLoads.contains(name))
InputStream in = getParentClassLoader().getResourceAsStream(classNameToPath(name));

if (in == null)
throw new ClassNotFoundException(name);

byte[] bytes = null;

try
{
bytes = IOUtil.getBytes(in);
}
catch(IOException e)
{
throw new ClassNotFoundException(name, e);
}
finally
{
InputStream in = getResourceAsStream(classNameToPath(name));

if (in == null)
throw new ClassNotFoundException(name);

byte[] bytes = null;

try
{
bytes = IOUtil.getBytes(in);
}
catch (IOException e)
{
throw new ClassNotFoundException(name, e);
}
finally
{
IOUtil.close(in);
}

clazz = defineClass(name, bytes, 0, bytes.length);
IOUtil.close(in);
}

clazz = defineClass(name, bytes, 0, bytes.length);
}

if (clazz == null)
// 此时仅代理父类加载JDK扩展库,其他都应由此类加载器加载
if (clazz == null && isJDKExtClassName(name))
{
ClassLoader parent = getParentClassLoader();

Expand All @@ -242,9 +240,36 @@ protected synchronized Class<?> loadClass(String name, boolean resolve)
if (resolve)
resolveClass(clazz);

if (LOGGER.isDebugEnabled())
LOGGER.debug("load class [" + (clazz == null ? "null" : clazz.getName()) + "] for name [" + name
+ "] in path [" + getPath() + "]");

return clazz;
}

/**
* 是否JDK标准类名。
*
* @param name
* @return
*/
protected boolean isJDKStandardClassName(String name)
{
return (name.startsWith("java.") || name.startsWith("javax."));
}

/**
* 是否JDK扩展类名。
*
* @param name
* @return
*/
protected boolean isJDKExtClassName(String name)
{
return (name.startsWith("sun.") || name.startsWith("org.ietf.") || name.startsWith("org.omg.")
|| name.startsWith("org.w3c.") || name.startsWith("org.xml."));
}

/**
* 获取上级类加载器。
*
Expand Down

0 comments on commit a9b0294

Please sign in to comment.