Issue #1448 - Eliminating Resource creation from TypeUtil.getLoadedFrom()

+ Replaced with URI TypeUtil.getLocationOfClass(Class clazz)
+ and File TypeUtil.getLocationOfClassAsFile(Class clazz)
+ This is done to eliminate extraneous "new URL" and "URI.toURL" calls
  that can trigger URL Stream Handler creation and initialization
  which is the cause of the StackOverflowError
This commit is contained in:
Joakim Erdfelt 2017-04-24 09:36:38 -07:00 committed by Greg Wilkins
parent 8c26eddbc6
commit 6ca9bacee6
5 changed files with 80 additions and 61 deletions

View File

@ -640,7 +640,10 @@ public class AnnotationConfiguration extends AbstractConfiguration
public Resource getJarFor (ServletContainerInitializer service)
throws MalformedURLException, IOException
{
return TypeUtil.getLoadedFrom(service.getClass());
URI uri = TypeUtil.getLocationOfClass(service.getClass());
if (uri == null)
return null;
return Resource.newResource(uri);
}
/**

View File

@ -18,12 +18,15 @@
package org.eclipse.jetty.util;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
@ -37,7 +40,6 @@ import java.util.Objects;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
/* ------------------------------------------------------------ */
@ -699,36 +701,48 @@ public class TypeUtil
}
/* ------------------------------------------------------------ */
public static Resource getLoadedFrom(Class<?> clazz)
public static URI getLocationOfClass(Class<?> clazz)
{
ProtectionDomain domain = clazz.getProtectionDomain();
if (domain!=null)
try
{
CodeSource source = domain.getCodeSource();
if (source!=null)
ProtectionDomain domain = clazz.getProtectionDomain();
if (domain != null)
{
URL location = source.getLocation();
if (location!=null)
return Resource.newResource(location);
CodeSource source = domain.getCodeSource();
if (source != null)
{
URL location = source.getLocation();
if (location != null)
return location.toURI();
}
}
String resourceName = clazz.getName().replace('.', '/') + ".class";
ClassLoader loader = clazz.getClassLoader();
URL url = (loader == null ? ClassLoader.getSystemClassLoader() : loader).getResource(resourceName);
if (url != null)
{
return URIUtil.getJarSource(url.toURI());
}
}
String rname = clazz.getName().replace('.','/')+".class";
ClassLoader loader = clazz.getClassLoader();
URL url = (loader==null?ClassLoader.getSystemClassLoader():loader).getResource(rname);
if (url!=null)
catch (URISyntaxException e)
{
try
{
return Resource.newResource(URIUtil.getJarSource(url.toURI()));
}
catch(Exception e)
{
LOG.debug(e);
}
}
LOG.debug(e);
}
return null;
}
/* ------------------------------------------------------------ */
public static File getLocationOfClassAsFile(Class<?> clazz)
{
URI uri = getLocationOfClass(clazz);
if (uri != null && "file".equalsIgnoreCase(uri.getScheme()))
{
return new File(uri);
}
return null;
}
}

View File

@ -22,7 +22,6 @@ package org.eclipse.jetty.util;
import org.eclipse.jetty.toolchain.test.JDK;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
public class TypeUtilTest
@ -124,20 +123,19 @@ public class TypeUtilTest
}
@Test
public void testLoadedFrom() throws Exception
public void testGetLocationOfClass() throws Exception
{
Assume.assumeFalse(JDK.IS_9);
Assert.assertThat(TypeUtil.getLoadedFrom(String.class).toString(),Matchers.containsString("/rt.jar"));
Assert.assertThat(TypeUtil.getLoadedFrom(Assert.class).toString(),Matchers.containsString(".jar"));
Assert.assertThat(TypeUtil.getLoadedFrom(TypeUtil.class).toString(),Matchers.containsString("/classes/"));
}
@Test
public void testLoadedFrom9() throws Exception
{
Assume.assumeTrue(JDK.IS_9);
Assert.assertThat(TypeUtil.getLoadedFrom(String.class).toString(),Matchers.containsString("jrt:/java.base/java/lang/String.clas"));
Assert.assertThat(TypeUtil.getLoadedFrom(Assert.class).toString(),Matchers.containsString(".jar"));
Assert.assertThat(TypeUtil.getLoadedFrom(TypeUtil.class).toString(),Matchers.containsString("/classes/"));
// Classes from maven dependencies
Assert.assertThat(TypeUtil.getLocationOfClass(Assert.class).toASCIIString(),Matchers.containsString("/repository/"));
// Class from project dependencies
Assert.assertThat(TypeUtil.getLocationOfClass(TypeUtil.class).toASCIIString(),Matchers.containsString("/classes/"));
// Class from JVM core
String expectedJavaBase = "/rt.jar";
if(JDK.IS_9)
expectedJavaBase = "/java.base/";
Assert.assertThat(TypeUtil.getLocationOfClass(String.class).toASCIIString(),Matchers.containsString(expectedJavaBase));
}
}

View File

@ -20,6 +20,7 @@
package org.eclipse.jetty.webapp;
import java.io.File;
import java.net.URI;
import java.net.URL;
import java.nio.file.Path;
import java.util.AbstractSet;
@ -515,10 +516,9 @@ public class ClasspathPattern extends AbstractSet<String>
try
{
Boolean byName = _patterns.isIncludedAndNotExcluded(clazz.getName());
Resource resource = TypeUtil.getLoadedFrom(clazz);
Boolean byLocation = resource == null || resource.getFile() == null
? null
: _locations.isIncludedAndNotExcluded(resource.getFile().toPath());
File locationFile = TypeUtil.getLocationOfClassAsFile(clazz);
Boolean byLocation = locationFile == null ? null
: _locations.isIncludedAndNotExcluded(locationFile.toPath());
// Combine the tri-state match of both IncludeExclude Sets
boolean included = byName==Boolean.TRUE || byLocation==Boolean.TRUE
@ -548,9 +548,12 @@ public class ClasspathPattern extends AbstractSet<String>
Boolean byLocation = null;
try
{
Resource resource = Resource.newResource(URIUtil.getJarSource(url.toURI()));
File file = resource.getFile();
byLocation = _locations.isIncludedAndNotExcluded(file.toPath());
URI jarUri = URIUtil.getJarSource(url.toURI());
if ("file".equalsIgnoreCase(jarUri.getScheme()))
{
File file = new File(jarUri);
byLocation = _locations.isIncludedAndNotExcluded(file.toPath());
}
}
catch(Exception e)
{

View File

@ -18,16 +18,17 @@
package org.eclipse.jetty.webapp;
import java.io.File;
import java.util.Arrays;
import org.eclipse.jetty.toolchain.test.JDK;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.resource.Resource;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import sun.security.provider.Sun;
public class ClasspathPatternTest
@ -118,23 +119,23 @@ public class ClasspathPatternTest
Assume.assumeFalse(JDK.IS_9);
// jar from JVM classloader
Resource loc_string = TypeUtil.getLoadedFrom(String.class);
File loc_string = TypeUtil.getLocationOfClassAsFile(String.class);
// System.err.println(loc_string);
// another jar from JVM classloader
Resource loc_jsse = TypeUtil.getLoadedFrom(Sun.class);
File loc_jsse = TypeUtil.getLocationOfClassAsFile(Sun.class);
// System.err.println(loc_jsse);
// a jar from maven repo jar
Resource loc_junit = TypeUtil.getLoadedFrom(Test.class);
File loc_junit = TypeUtil.getLocationOfClassAsFile(Test.class);
// System.err.println(loc_junit);
// a jar from another maven repo jar
Resource loc_tool = TypeUtil.getLoadedFrom(JDK.class);
File loc_tool = TypeUtil.getLocationOfClassAsFile(JDK.class);
// System.err.println(loc_tool);
// class file
Resource loc_test = TypeUtil.getLoadedFrom(ClasspathPatternTest.class);
File loc_test = TypeUtil.getLocationOfClassAsFile(ClasspathPatternTest.class);
// System.err.println(loc_test);
ClasspathPattern pattern = new ClasspathPattern();
@ -146,7 +147,7 @@ public class ClasspathPatternTest
Assert.assertThat(pattern.match(ClasspathPatternTest.class), Matchers.is(false));
// Add directory for both JVM classes
pattern.include(loc_string.getFile().getParentFile().toURI().toString());
pattern.include(loc_string.getParentFile().toURI().toString());
// Add jar for individual class and classes directory
pattern.include(loc_junit.toString(), loc_test.toString());
@ -173,23 +174,23 @@ public class ClasspathPatternTest
Assume.assumeFalse(JDK.IS_9);
// jar from JVM classloader
Resource loc_string = TypeUtil.getLoadedFrom(String.class);
File loc_string = TypeUtil.getLocationOfClassAsFile(String.class);
// System.err.println(loc_string);
// another jar from JVM classloader
Resource loc_jsse = TypeUtil.getLoadedFrom(Sun.class);
File loc_jsse = TypeUtil.getLocationOfClassAsFile(Sun.class);
// System.err.println(loc_jsse);
// a jar from maven repo jar
Resource loc_junit = TypeUtil.getLoadedFrom(Test.class);
File loc_junit = TypeUtil.getLocationOfClassAsFile(Test.class);
// System.err.println(loc_junit);
// a jar from another maven repo jar
Resource loc_tool = TypeUtil.getLoadedFrom(JDK.class);
File loc_tool = TypeUtil.getLocationOfClassAsFile(JDK.class);
// System.err.println(loc_tool);
// class file
Resource loc_test = TypeUtil.getLoadedFrom(ClasspathPatternTest.class);
File loc_test = TypeUtil.getLocationOfClassAsFile(ClasspathPatternTest.class);
// System.err.println(loc_test);
ClasspathPattern pattern = new ClasspathPattern();
@ -204,7 +205,7 @@ public class ClasspathPatternTest
Assert.assertThat(pattern.match(ClasspathPatternTest.class), Matchers.is(true));
// Add directory for both JVM classes
pattern.exclude(loc_string.getFile().getParentFile().toURI().toString());
pattern.exclude(loc_string.getParentFile().toURI().toString());
// Add jar for individual class and classes directory
pattern.exclude(loc_junit.toString(), loc_test.toString());