在调用loadClass()a时ClassLoader,是否ClassLoader首先检查是否已加载该类,还是立即将此检查委托给其父级ClassLoader?
Java API说:
当请求查找类或资源时,ClassLoader实例会在尝试查找类或资源本身之前,将对类或资源的搜索委托给其父类加载器.
但是在Java Reflection in Action一书中有一个关于类加载器的特定章节,它说:
类加载器调用findLoadedClass来检查是否已经加载了类.如果类加载器没有找到加载的类,则在父类加载器上调用loadClass.
哪个是对的?
我想在我的方法内部编写一个代码,用于打印哪个方法/类调用它.
(我的假设是我不能改变任何东西,除了我的方法..)
其他编程语言怎么样?
编辑:谢谢你们,JavaScript怎么样?蟒蛇?C++?
在C#或.net IL中是否有办法强制一个具有类型初始值设定项(静态构造函数)的类来加载自身,而不访问它的任何参数?
假设我上了课
public static class LogInitialization {
static LogInitialization() {
System.Console.WriteLine("Initialized");
}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法让这条线打印出来?
请注意,该类是静态的,因此我无法将其实例化以强制初始化,并且它没有公共成员,因此我无法访问它们以启动它.
我正在使用自定义类加载器加载类.在大多数情况下,一切正常,但有时当我加载特别复杂的项目/库时,我得到一个奇怪的错误:
Exception in thread "main" java.lang.ClassCircularityError:
org/apache/commons/codec/binary/Hex
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
at java.lang.ClassLoader.defineClass(ClassLoader.java:466)
at my.custom.class.Loader.loadClass(...)
Run Code Online (Sandbox Code Playgroud)
看看Javadocs,我不希望defineClass抛出这个特殊的错误. org/apache/commons/codec/binary/Hex是我正在尝试加载的类.defineClass在它定义类之前,它几乎就像想要一个类的副本 - 这对我来说毫无意义.
想法?
默认情况下,Sun的JVM都懒惰地加载类并且懒惰地初始化(即调用它们的<clinit>方法)它们.考虑以下类,ClinitBomb它Exception在static{}块中抛出一个.
public class ClinitBomb {
static {
explode();
}
private static void explode() {
throw new RuntimeException("boom!");
}
}
Run Code Online (Sandbox Code Playgroud)
现在,考虑如何触发炸弹:
public class Main {
public static void main(String[] args) {
System.out.println("A");
try {
Class.forName("ClinitBomb");
} catch (Exception e) {
e.printStackTrace(System.out);
}
System.out.println("B");
ClinitBomb o2 = new ClinitBomb();
System.out.println("C");
}
}
Run Code Online (Sandbox Code Playgroud)
我们保证爆炸发生在B点之前,因为forName文件说明了这一点; 问题是它是否发生在A点之前(Main加载时).在Sun的JVM中,即使main()包含静态引用ClinitBomb,它也会在A之后发生.
我想要一种方法告诉JVM ClinitBomb一旦初始化就加载并初始化Main(因此炸弹在 A点之前爆炸).一般来说,我想要一种方式来说,"无论何时加载/初始化类X,对任何一个也是如此它引用的Y类."
有没有办法做到这一点?
我有孩子优先的UrlClassLoader来动态加载jar文件.然后我做一个反射来调用加载的jar文件中的方法.一旦完成,我宁愿卸载类加载器.然后我尝试做一些压力测试代码,以确保我的代码顺利运行.基本上,我尝试做的是在循环语句中加载和卸载jar.这是我的代码:
for (int i = 0; i < 1000; i++) {
//Just to show the progress
System.out.println("LOAD NUMBER : " + i);
ChildFirstURLClassLoader classLoader = null;
try {
File file = new File("C:\\library.jar");
String classToLoad = "com.test.MyClass";
URL jarUrl = new URL("file:" + file.getAbsolutePath());
classLoader = new ChildFirstURLClassLoader(new URL[] {jarUrl}, null);
Class<?> loadedClass = classLoader.loadClass(classToLoad);
Method method = loadedClass.getDeclaredMethod("execute",
new Class[] {});
ClassLoader currCl= Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(classLoader);
method.invoke(null);
Thread.currentThread().setContextClassLoader(currCl);
method = null;
loadedClass = null;
} finally {
if (classLoader != …Run Code Online (Sandbox Code Playgroud) 假设在我的JVM中我有一个加载的类Class<C> myClass.有可靠吗?方法向JVM询问字节码.class的内容?就是这样的:
<C> byte[] getClassBytecode(Class<C> myClass) {
return /* the contents of the .class resource where C was loaded from */;
}
Run Code Online (Sandbox Code Playgroud)
(显然InputStream会和它一样好byte[]).我知道我可以使用myClass.getResource()(和朋友)来获取类文件,但是在类名上敲击以获取一个提供给getResource的URL感觉不对.此外,我不确定在C动态生成(例如使用javax.tools.JavaCompiler)的情况下这将如何表现.
任何(更好)的想法?
注意:目标是能够推动 字节码 类到不同的JVM并使用自定义类加载器在那里加载它们
在Java 7中加载KeyStore时,类加载器被泄露.
我已经使用Tomcat 7.0.47中的"Find Leaks"功能和classloader-leak-prevention确认了这一点.这是测试代码,带有@Configuration泄漏的webapp和带有@Controller泄漏的webapp.
基本上这些线为我造成了泄漏:
InputStream is = null;
try {
is = new FileInputStream("./app.truststore");
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(is, "changeit".toCharArray());
} catch (Exception e) {
System.out.println(e);
} finally {
if (is != null) {
is.close();
}
}
Run Code Online (Sandbox Code Playgroud)
如果我删除KeyStore.load()一切正常,但这显然不是一个有效的解决方案.
它不适用于Oracle JDK 1.7u15,u17,u21,u25,u40和u45以及OpenJDK 1.7u40和u45.
它适用于Oracle JDK 1.6u39,u41,u43和45以及OpenJDK 1.6.0.
这是在Microsoft Windows Server 2008 R2 Standard 64 Bit上测试的.OpenJDKs是alexkasko在GitHub上的最新非官方版本.
有谁知道可能导致Classloader泄漏的原因是什么?我尝试使用堆转储并调用"GC根目录的最短路径",但没有返回任何结果.
我确实遇到过TestNG和RESTeasy的烦人问题.
我有一个类,它针对API类运行多个测试,该类使用RESTeasy框架来暴露自己.
但是,如果我让测试运行maven(mvn test),那么我得到以下异常:
java.lang.LinkageError: ClassCastException: attempting to castjar:file:/C:/Users/rit/.m2/repository/org/jboss/resteasy/jaxrs-api/2.3.0.GA/jaxrs-api-2.3.0.GA.jar!/javax/ws/rs/ext/RuntimeDelegate.classtojar:file:/C:/Users/rit/.m2/repository/org/jboss/resteasy/jaxrs-api/2.3.0.GA/jaxrs-api-2.3.0.GA.jar!/javax/ws/rs/ext/RuntimeDelegate.class
at javax.ws.rs.ext.RuntimeDelegate.findDelegate(RuntimeDelegate.java:126)
at javax.ws.rs.ext.RuntimeDelegate.getInstance(RuntimeDelegate.java:96)
at javax.ws.rs.core.Response$ResponseBuilder.newInstance(Response.java:394)
at javax.ws.rs.core.Response.status(Response.java:116)
at javax.ws.rs.core.Response.status(Response.java:130)
at com.pd.api.TokenAPI_V1.validateAccessToken(TokenAPI_V1.java:141)
at com.test.pd.api.TokenAPI_V1Test.testIfValidAccessTokenReturnsCorrectHTTPHeadersWhenTokenIsNotFound(TokenAPI_V1Test.java:359)
Run Code Online (Sandbox Code Playgroud)
测试只是调用API obejct的方法,该方法返回一个Response对象(来自RESTeasy).作为测试框架,我使用TestNG.
测试方法
@Test
public void testIfValidAccessTokenReturnsCorrectHTTPHeadersWhenTokenIsNotFound() throws InvalidAccessTokenException {
Mockito.when(tokenService.validateAccessToken(TestConstants.ACCESS_TOKEN)).thenThrow(new InvalidAccessTokenException());
Response response = tokenAPI_v1.validateAccessToken(TestConstants.ACCESS_TOKEN, TestConstants.USER_AGENT);
assert "no-store".equals(response.getMetadata().getFirst("Cache-Control"));
assert "no-cache".equals(response.getMetadata().getFirst("Pragma"));
}
Run Code Online (Sandbox Code Playgroud)
问题说明
看起来RESTeasy框架在不同的类加载器中加载RuntimeDelegate.如果我看一下源代码,那么在RuntimeDelegate(包括第126行)中有以下方法:RuntimeDelegate.java.
因此,与错误相关的主要语句是instanceof check:
if (!(delegate instanceof RuntimeDelegate))
Run Code Online (Sandbox Code Playgroud)
如果我检查委托实例的类加载器与RuntimeDelegate的类加载器,那么我得到以下输出:
delegate.getClass().getClassLoader() -> org.powermock.core.classloader.MockClassLoader@31e46a68
RuntimeDelegate.class.getClassLoader() -> sun.misc.Launcher$AppClassLoader@3c0fabe9
Run Code Online (Sandbox Code Playgroud)
我知道这当然不起作用,但我想知道为什么RESTeasy的东西被加载到MockClassLoader而不是另一个.特别是因为我没有模拟被测试的TokenAPI.
奇怪的事实
奇怪的是,当我从IntelliJ运行测试时(我选择只运行包含产生错误的方法的给定类的所有测试),然后它就会运行.看起来它与mvn测试运行maven项目中的所有测试(或者至少我认为是这样)的事实有某种关系.
我想知道以下两者之间的区别:
MyClass.class.getClassLoader().getResourceAsStream("path/to/my/properties");
和
MyClass.class.getResourceAsStream("path/to/my/properties");
谢谢.
classloader ×10
java ×9
class ×2
memory-leaks ×2
.net ×1
c# ×1
javascript ×1
mockito ×1
powermock ×1
python ×1
testng ×1