说我有一个名为的班级NameGenerator.我可以使用它来根据给定的逻辑生成名称.然后我TestNameGeneration用一个方法编写一个类,该方法要求用户写一封信并按照生成名称.现在我想更改NameGeneration类中的逻辑并应用该特定更改而不停止应用程序.
我这样做是为了更多地了解类加载器,有人可以解释一下我必须学习做的事情或网站任何参考的关键概念吗?
这是一个常见问题.我正在使用2个库A.jar和B.jar,这些库依赖于同一个jar的不同版本.
假设在运行时我需要THIS.xxxjar
MY.jar
-> A.jar -> THIS.1.0.0.jar
-> B.jar -> C.jar -> THIS.5.0.0.jar
Run Code Online (Sandbox Code Playgroud)
我可以针对它的依赖编译特定的jar(A.jar/B.jar)但是在运行时我只能加载1个版本.哪一个?
仅加载1个依赖项(最新版本)意味着如果库不是向后兼容的,那么我的代码可能会抛出运行时异常(那里有向后兼容的库吗?).
无论如何,我知道像OSGi这样的东西可以解决这个问题.
我想知道解决这类问题的旧方法是什么......
非常感谢
假设我有以下课程:
class Caller {
public void createSomething() {
new Something();
}
}
Run Code Online (Sandbox Code Playgroud)
会执行这一行:
static void main() {
Class<?> clazz = Caller.class;
}
Run Code Online (Sandbox Code Playgroud)
导致JVM加载类Something或者是在createSomething()调用方法之前延迟的类加载?
我不能在JLS/JVMSpec中找到它,也不能在SO中找到它.我肯定一定会被问到......
那么,"新"究竟做了什么?假设我们在A中实例化一个B类:
class A {
// ...
new B();
// ...
}
Run Code Online (Sandbox Code Playgroud)
这相当于
class A {
// ...
A.class.getClassLoader().loadClass("B's canonical name").newInstance();
// ...
}
Run Code Online (Sandbox Code Playgroud)
?
它是,还是在每个环境中都不像那样?
如果您能指出JLS/JVMSpec中的相应章节,我将不胜感激.谢谢!
编辑:我们肯定不能叫B.class.getCanonicalName()在loadClass()打电话,因为B的尚未加载.JVM必须根据import语句解析名称.
A有一个Java代码:
public class Hello
{
public void print()
{
System.out.println("Hi");
}
}
Run Code Online (Sandbox Code Playgroud)
我编译了它并创建了一个Hello.class.我将它添加到Jar文件hello.jar中:
$jar -cvf hello.jar Hello.class
Run Code Online (Sandbox Code Playgroud)
我又写了一个程序:
class Test1
{
public static void main(String[] args)
{
new Hello().print();
System.out.println(Hello.class.getClassLoader());
}
}
Run Code Online (Sandbox Code Playgroud)
并从当前目录中删除了Hello.class.
然后我在扩展类路径中复制了hello.jar.我的程序工作正常:
$sudo cp hello.jar /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext
$ java Test1
Hi
sun.misc.Launcher$ExtClassLoader@28d93b30
$
Run Code Online (Sandbox Code Playgroud)
如果我从扩展类路径中删除hello.jar并将其复制到包含rt.jar的boot strap类路径(usr/lib/jvm/java-8-openjdk-amd64/jre/lib /)中,那么我的程序不是工作.
$ java Test1
Exception in thread "main" java.lang.NoClassDefFoundError: Hello
at Test1.main(Test1.java:5)
Caused by: java.lang.ClassNotFoundException: Hello
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 1 more
Run Code Online (Sandbox Code Playgroud)
根据我的知识,bootstrap或扩展类加载器中的所有jar文件都可以在程序中使用.为什么Java会抛出异常,如果它是正确的?如果我不对,请指导我.
我想在运行时确定我的应用程序启动的类名,带有main()方法的类名,但我在另一个线程中,我的堆栈跟踪不会一直回到原始类.
我搜索了系统属性以及ClassLoader提供的所有内容,并且没有提供任何内容.这些信息不可用吗?
谢谢.
我是新来的,我为我糟糕的英语道歉.
我对Java Web Start技术服务的Applet类有一点问题.我有一些平台依赖的JAR文件,Web Start正确下载,但是当我通过对象的getResourceAsStream(String fileName)方法获取内容时ClassLoader,首先fileName向WEB服务器发出GET请求,收到404 Not Found响应后,资源从JAR文件正确加载.问题是我在JAR中有很多文件,所以我在WEB服务器上有很多不必要的负载,因此我必须等待很长时间才能使用Applet.
在Google上搜索我发现了一些讨论据说添加参数codebase_lookup值false,但这并没有解决问题.此页面与codebase_lookup参数相关,表示Applet的默认行为是从JAR文件加载资源,然后从Applet代码库加载,在我的情况下,行为是相反的.
我还eager="true"为.jnlp文件中的每个JAR资源添加了属性,但行为始终相同.Applet是使用NetBeans开发和构建的,生成的html和jnlp文件如下.
launch.html
<applet width="300" height="300">
<param name="jnlp_href" value="launch.jnlp"/>
<param name="codebase_lookup" value="false"/>
</applet>
Run Code Online (Sandbox Code Playgroud)
launch.jnlp
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<jnlp codebase="http://192.168.23.4/contact" href="launch.jnlp" spec="1.0+">
<information>
<title>ContactNR</title>
<vendor>Roberto Santini</vendor>
<homepage href=""/>
<description>ContactNR</description>
<description kind="short">ContactNR</description>
</information>
<resources>
<j2se version="1.5+"/>
<jar eager="true" href="ContactNR.jar" main="true"/>
<jar eager="true" href="lib/VDK.jar"/>
<security>
<all-permissions/>
</security>
</resources>
<resources arch="amd64" os="Linux">
<jar eager="true" href="lib/liblinux64.jar"/> …Run Code Online (Sandbox Code Playgroud) 我在课程开头有这个:
@Grab(group = 'org.ccil.cowan.tagsoup', module = 'tagsoup', version = '1.2')
class MyClass{...
Run Code Online (Sandbox Code Playgroud)
我正在尝试对这个类进行单元测试,但每当我尝试运行JUnit 4测试时,我都会收到此错误:
Caused by: java.lang.RuntimeException: No suitable ClassLoader found for grab
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:77)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:102)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:52)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:190)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:198)
at groovy.grape.GrapeIvy.chooseClassLoader(GrapeIvy.groovy:163)
at groovy.grape.GrapeIvy$chooseClassLoader.callCurrent(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:44)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:149)
at groovy.grape.GrapeIvy.grab(GrapeIvy.groovy:227)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:225)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:51)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:44)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:153)
at groovy.grape.GrapeIvy.grab(GrapeIvy.groovy:216)
at groovy.grape.Grape.grab(Grape.java:131)
at groovy.grape.Grape$grab.callStatic(Unknown Source)
at …Run Code Online (Sandbox Code Playgroud) 我在我的Android应用程序中使用了一些本机库,我想在某个时间点将它们从内存中卸载.当加载了加载本机库的类的ClassLoader被垃圾收集时,库将被卸载.灵感:原生卸货.
在下面的代码中,我通过省略本机库加载代码来简化案例,只演示了Classloader内存泄漏.
我在Android KitKat 4.4.2,API 19上测试了它.设备:Motorola Moto G.
为了演示,我有以下ClassLoader,派生自PathClassLoader用于加载Android应用程序.
package com.demo;
import android.util.Log;
import dalvik.system.PathClassLoader;
public class LibClassLoader extends PathClassLoader {
private static final String THIS_FILE="LibClassLoader";
public LibClassLoader(String dexPath, String libraryPath, ClassLoader parent) {
super(dexPath, libraryPath, parent);
}
@Override
protected void finalize() throws Throwable {
Log.v(THIS_FILE, "Finalizing classloader " + this);
super.finalize();
}
}
Run Code Online (Sandbox Code Playgroud)
我有EmptyClass加载LibClassLoader.
package com.demo;
public class EmptyClass {
}
Run Code Online (Sandbox Code Playgroud)
内存泄漏是由以下代码引起的:
final Context …Run Code Online (Sandbox Code Playgroud) android garbage-collection memory-leaks classloader native-code
在使用jhat分析堆转储的同时,我观察到了许多DelegatingClassLoader实例,虽然它们没有在代码中显式调用.我希望这是一种反射优化机制.有人知道细节吗?
classloader ×10
java ×7
jar ×3
jvm ×3
reflection ×2
android ×1
applet ×1
dependencies ×1
groovy ×1
junit4 ×1
memory-leaks ×1
native-code ×1
runtime ×1
stack-trace ×1
versions ×1