这个问题一直困扰着我.我必须在我的java应用程序中加载几个文件,到目前为止我工作的唯一方法是这样的:
URL hsURL;
if(System.getProperty("os.name").toLowerCase().contains("windows")) {
hsURL = new URL("file:/" + System.getProperty("user.dir") + "/helpsets/helpset.hs");
}
else {
hsURL = new URL("file://" + System.getProperty("user.dir") + "/helpsets/helpset.hs");
}
Run Code Online (Sandbox Code Playgroud)
但这是丑陋可怕的.有一段时间我以为我有这个工作:
hsURL = ClassLoader.getSystemResource("helpsets/helpset.hs");
Run Code Online (Sandbox Code Playgroud)
但是由于某些原因它不再起作用(我必须改变一些东西而不是注意到它.它返回null.
我应该使用getResource()而不是getSystemResource()(如果是这样,为什么getSystemResource()是静态的而不是getResource())?
我正在使用eclipse,我尝试在构建路径(classpath)中包含该文件夹而不包括它,它似乎没有什么区别.
您可能会问,为什么我要这样做 - 这是因为我正在使用一个类(来自外部库),它在静态初始化程序中执行操作,我需要知道它是否已经完成.
我看了看ClassLoader,但没有找到任何看起来有用的东西.有任何想法吗?
我一直在与一些内存泄漏作斗争,我目前对这个问题感到困惑.有一个Web应用程序类加载器,应该是垃圾收集,但它不是(即使我修复了几个泄漏).我用jmap转储堆并用jhat浏览它,找到了类加载器并检查了rootset引用.
如果我排除弱参考,列表是空的!这怎么可能,因为只有弱引用持有的对象应该收集垃圾?(我在jconsole中多次执行GC)
如果我包含弱引用,我会得到一个引用列表,所有引用都来自以下某个字段:
我找不到任何理由为什么这些引用应该防止垃圾收集类加载器.这是一个gc bug吗?特殊无证案件?jmap/jhat bug?或者是什么?
最奇怪的是......在闲置和闲逛之后大约40分钟,没有改变任何东西,它最终决定卸载类并收集类加载器.
注意:
如果您对延迟收集类加载器或弱引用提出声明,请说明发生的情况,理想情况是:
如果您认为该行为是依赖于实现的,那么请关注oracle或icedtea jvm版本6或7中发生的事情(选择其中任何一个并具体说明).
我真的想深究这一点.我实际上已经花了一些力气来重现测试程序中的问题,但我失败了 - 除非有强烈的引用,否则每次都会立即在System.gc()上收集类加载器.
我有一个spring mvc web应用程序,我需要更改类加载器.我需要将类加载器更改为等于PARENT_LAST.我正在使用WAS 6.1并且已经有一个jacl脚本来自我之前可以复制的Web应用程序来完成这项工作.
在最后一个应用程序中使用了Apache ant,他们所做的是使部署依赖于运行jacl脚本.
在我的新Web应用程序中,我使用maven install来创建war文件,并将该war文件部署到我的应用程序服务器.
如何使用maven将类加载器设置为PARENT_LAST?我知道如何在控制台中执行此操作,但如果有办法使用脚本执行它会很好.
此设置也将放置在war文件中的某个位置,以便在部署应用程序时将获取该设置.这个问题来自于我对jacl脚本如何工作缺乏了解?
谢谢
假设如下:
@SomeAnnotation
public interface Foo {
}
Run Code Online (Sandbox Code Playgroud)
我想知道是否始终如此定义的类加载器SomeAnnotation等于或者是启动类加载器的父类Foo.
我已阅读JVMS v8第5.3节.但我不确定这里适用的是什么.第5.3.4节讨论了加载约束,但它们似乎不适用于注释.
我问的问题是因为这样的代码:
Class<?> fooClass = //will in some way obtain a reference to class Foo
fooClass.getAnnotation(SomeAnnotation.class);
Run Code Online (Sandbox Code Playgroud)
在不同的类加载器存在的情况下会失败.我知道我可以使用getAnnotations并在结果数组中搜索类名等于的名称的元素SomeAnnotation.但我想知道以下是否也会有效:
Class<?> fooClass = //will in some way obtain a reference to class Foo
fooClass.getAnnotation((Class<? extends Annotation>) fooClass
.getClassLoader().loadClass(SomeAnnotation.class.getName()));
Run Code Online (Sandbox Code Playgroud) 我对tomcat中类加载的发生方式感到困惑.如果我的问题听起来很愚蠢,请耐心等待.
我们在单个tomcat服务器上部署多个spring webapps.为了减少内存占用,我们考虑在tomcat lib文件夹中安装spring,hibernate和数据库驱动程序jar,以便所有webapp共享.
我首先将spring依赖关系标记为,provided然后将这些jar复制到tomcat lib.但是,在服务器启动时,我开始越来越多ClassNotFoundErrors,像commons-logging,commons-fileupload,jackson,所以我必须将这些罐子以及到Tomcat的lib.
但后来开始感觉很可疑.如果将来我在项目中添加另一个spring依赖项,比如spring-data-cassandra.我是否还需要移动它的依赖罐子?这可能是无止境的.另外,我可能会在运行时遇到CNF错误.
我试图按照这个链接,将spring-context和spring-web带回应用程序之战.但它没有用,在WebApplicationIntializer初始化期间在某些类上得到了ClassNotFound .我试图理解在tomcat中加载的类的顺序,但是不太了解.
然后我找到了一个完全不同的JDBC驱动程序加载解释,这与所有其他解释相矛盾,让我完全糊涂了.
在我阅读更多内容时,我认为将弹簧罐移动到tomcat lib并不是一种正确的方法,但仍然没有一个好的推理.然后为什么JDBC驱动程序有效?有人可以解释一下吗?每个webapp的classloader也会创建每个类的副本吗?
编辑1:我开始知道optional春季罐子中有很少的依赖项,如果在我的webapp中使用它将是必需的.所以spring-web依赖于jackson库,但对于我的应用程序是可选的.因此,我需要找出我的项目所需的所有罐子,并且春天也需要这些罐子,这些罐子需要移动到tomcat lib.
我使用sbt程序集插件将一个spark工作打包为uber-jar.该build.sbt指定可运行的主要得到的尤伯杯罐的目标
mainClass in assembly := Some("com.foo.Bar")
Run Code Online (Sandbox Code Playgroud)
正确创建程序集后,运行预期的命令:
java -jar assembly.jar
Run Code Online (Sandbox Code Playgroud)
结果是
错误:无法找到或加载主类com.foo.Bar
使用替代方法,就像java -cp assembly.jar com.foo.Bar给出相同的错误消息.
然后,我在新目录中提取了超级jar的内容.我可以看到我的com/foo/目录和Bar.class文件.从我提取的目录的根目录我尝试:
java -cp . com.foo.Bar
Run Code Online (Sandbox Code Playgroud)
我得到了正确的结果.
进一步试图找出错误的原因,我试过:
java -verbose -jar assembly.jar
Run Code Online (Sandbox Code Playgroud)
我可以看到正在加载java核心类,但我没有看到我的任何打包类被加载.
这可能有什么问题?
我想知道是否或如何处理直接或间接从我的应用程序注册的MBean,该应用程序部署在servlet容器上.
在大多数情况下,有两个选项可用于检索MBeanServer可用于注册的选项
创建自己的MBeanServer使用MBeanServerFactory.createMBeanServer()
使用 ManagementFactory.getPlatformMBeanServer()
使用第一个选项时,可以轻松取消注册所有MBean:只需调用即可MBeanServer.releaseMBeanServer(myMBeanServer).
但是,在许多第三方应用程序中经常使用的第二个选项呢?(顺便说一句,这也是Sun/Oracle的推荐方式).
因为使用了平台MBeanServer,所以当servlet上下文被销毁时它不会被注销 - 但更糟糕的是它仍然保留了对web应用程序类加载器的引用.
因此,Web应用程序的所有静态引用都不会被释放,从而导致泄漏.
如果您想测试一下:只需部署一个简单的Web应用程序,该应用程序分配一个100MB阵列,该阵列是静态引用,并使用oracle jdbc驱动程序(它将使用平台mbean服务器注册诊断MBean),部署在tomcat上.停止应用程序并重新启动它 - 重复此操作,然后你就可以了OutOfMemoryError.
问题:
我是否必须处理这些问题,或者是servlet容器和/或第三方库的问题?
有没有办法获取MBeanServer特定类加载哪些类的所有MBean ClassLoader?
我该怎么做才能防止这种情况发生?我是否必须跟踪平台的所有已注册MBean并在MBeanServer此期间取消注册contextDestroyed()?
Eclipse的JDT编译器提供了一个接口INameEnvironment,该接口定义了findType(...)使您能够进行级联编译的方法.奇怪的是我想知道是否有任何方法可以使用标准的JDK编译工具包来做到这一点?
注意,该场景是一个模板引擎,它在内存编译中为模板文件生成的类进行相互依赖,并且它无法预测您遇到模板文件的顺序,因此Foo可能需要先编译才能进行父Bar编译,因此你需要一个机制来进行级联编译,这意味着在编译期间Foo你需要生成另一个源Bar并首先编译它以便继续Foo编译:一些代码如下:
private NameEnvironmentAnswer findType(final String name) {
try {
if (!name.contains(TemplateClass.CN_SUFFIX)) {
return findStandType(name);
}
char[] fileName = name.toCharArray();
TemplateClass templateClass = classCache.getByClassName(name);
// TemplateClass exists
if (templateClass != null) {
if (templateClass.javaByteCode != null) {
ClassFileReader classFileReader = new ClassFileReader(templateClass.javaByteCode, fileName, true);
return new NameEnvironmentAnswer(classFileReader, null);
}
// Cascade compilation
ICompilationUnit compilationUnit = new CompilationUnit(name);
return new NameEnvironmentAnswer(compilationUnit, null);
}
// So it's …Run Code Online (Sandbox Code Playgroud) 似乎Android应用程序类加载器允许反射性地获取对public static包私有类的字段的引用,甚至来自不同的包(比上面定义的类中的那个),而Sun JDK类加载器例如没有.
更具体地说,给定以下类定义:
package org.example.a
class PackagePrivateClass {
public static final Parcelable.Creator<PackagePrivateClass> CREATOR = generateCreator();
}
Run Code Online (Sandbox Code Playgroud)
以下代码在一个单独的包中:
package org.example.b
public class TestClass {
public void testMethod() {
final Class classRef = Class.forName("org.example.a.PackagePrivateClass");
final Field creatorFieldRef = classRef.getField("CREATOR");
creatorFieldRef.get(null); // throws here (unless on Android)
}
}
Run Code Online (Sandbox Code Playgroud)
在Sun JVM上执行时,它会抛出IllegalAccessException最后一行:
java.lang.IllegalAccessException: Class org.example.b.TestClass can not access a member of class org.example.a.PackagePrivateClass with modifiers "public static final"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
...
Run Code Online (Sandbox Code Playgroud)
但是,当在Android设备(5.1 Lollipop FWIW)上运行时,它会在不抛出的情况下执行,并creatorFieldRef.get(null)实际返回对该CREATOR字段的有效引用.
我的问题是:为什么会这样?它是Android类加载器的错误还是功能?(或者,如果适用的话,我的例子中出了什么问题?)