我有一个TestThis.java像以下Java文件:
class A
{
public void foo()
{
System.out.println("Executing foo");
}
}
class B
{
public void bar()
{
System.out.println("Executing bar");
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码文件编译正常,没有任何警告/错误.有什么方法可以访问任何类A或B没有任何其他外部类的顶级类?
如果不是那么为什么Java甚至允许在没有顶级类的情况下编译这些文件呢?
我创建了一个包含一堆属性值的类.为了初始化该类,我必须调用一些静态方法"configure()",它从XML文件配置它.
该类应该用于存储一些数据,以便我可以写
PropClass.GetMyProperty();
Run Code Online (Sandbox Code Playgroud)
我configure()在main中调用了一个静态块,所以我可以在任何地方使用它
但
如果我将其他类的静态常量成员设置为我的"PropClass"中的值,我得到null,
class SomeClass {
static int myProp = PropClass.GetMyProperty();
}
Run Code Online (Sandbox Code Playgroud)
这可能是因为在调用configure之前计算了该表达式.我该如何解决这个问题?
如何强制configure()执行首先执行的调用?谢谢
我将基于Wicket的应用程序的.war文件部署到Jetty 7.0.2.问题是Jetty将类路径复制到临时目录,但只复制*.class,因此*.html不可用于类加载器,我得到错误:
WicketMessage:未找到组件'cz.dynawest.wicket.chat.ChatPage'的'html'类型标记.
将战争复制为扩展目录有帮助.不过,我想知道如何配置Jetty来复制一切.
而且,mvn jetty:run我得到了同样的错误.
谢谢,Ondra
我正在寻找类似于.NET托管扩展框架(http://mef.codeplex.com/)的Java功能。对于那些不了解MEF的人,我想要这样的东西:
给定接口
public interface IFoo {
...
}
Run Code Online (Sandbox Code Playgroud)
通过查看已加载的jar,动态加载接口的实现。
IFoo foo = loadClassThatImplementsInterface<IFoo>();
Run Code Online (Sandbox Code Playgroud)
关键是程序员在代码时不知道实现的名称,但在代码中提供了扩展点。
在Java中根本不可能吗?我发现一些Google命中说这是不可能的,但这似乎有点...是吗?
当在编译时知道实现的完全限定名称时,有许多使用类加载器的示例。那不是我想要的。
如何将Jboss中的类加载器的日志级别更改为7?
作为旁注; 我已经在Jboss 5及更低版本中找到了有关如何执行此操作的信息,但由于Jboss 7中的类加载和日志记录已完全更改,因此我无法弄清楚如何执行此操作.
我用Maven构建了一个war文件,它使用其他war叠加作为依赖...构建成功了.
但是在部署到Jboss时我收到以下错误:
11:27:49,054 ERROR [org.springframework.web.context.ContextLoader] (MSC service thread 1-1) .... nested exception is java.lang.NoClassDefFoundError: org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor
at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(ClassPathScanningCandidateComponentProvider.java:281) [spring-context-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:242) [spring-context-3.2.1.RELEASE.jar:3.2.1.RELEASE]
........
Run Code Online (Sandbox Code Playgroud)
所以我java.lang.NoClassDefFoundError上课了AnnotationMetadataReadingVisitor...基于异常,我假设该类在类路径上出现不止一次.
我已经验证org.springframework.core.type.classreading.AnnotationMetadataReadingVisitor了类路径上确实存在(在war文件中WEB-INF\lib\spring-core-3.2.1.RELEASE.jar).
但据我所知,它是我的类路径中唯一包含该类的jar.
知道我在这里缺少什么吗?
以下是WEB-INF\lib我正在尝试部署的战争的全部内容:
activemq-all-5.5.1.jar
ant-1.7.0.jar
ant-launcher-1.7.0.jar
antlr-2.7.7.jar
antlr-3.3.jar
antlr-runtime-3.3.jar
aopalliance-1.0.jar
aspectjweaver-1.7.1.jar
axiom-api-1.2.12.jar
axiom-dom-1.2.12.jar
axiom-impl-1.2.12.jar
axis2-1.6.1.jar
axis2-adb-1.6.1.jar
axis2-adb-codegen-1.6.1.jar
axis2-ant-plugin-1.6.1.jar
axis2-clustering-1.6.1.jar
axis2-codegen-1.6.1.jar
axis2-corba-1.6.1.jar
axis2-fastinfoset-1.6.1.jar
axis2-java2wsdl-1.6.1.jar
axis2-jaxbri-1.6.1.jar
axis2-jaxws-1.6.1.jar
axis2-jibx-1.6.1.jar
axis2-json-1.6.1.jar
axis2-kernel-1.6.1.jar
axis2-metadata-1.6.1.jar
axis2-mtompolicy-1.6.1.jar
axis2-saaj-1.6.1.jar
axis2-transport-http-1.6.1.jar
axis2-transport-local-1.6.1.jar
axis2-xmlbeans-1.6.1.jar
bcel-5.1.jar
blitzer-1.0.9.jar
c3p0-0.9.1.1.jar
camel-core-2.4.0.jar
camel-xstream-2.4.0.jar
cdjai-1.0.jar
commons-beanutils-1.7.0.jar
commons-cli-1.2.jar
commons-codec-1.3.jar
commons-collections-3.1.jar …Run Code Online (Sandbox Code Playgroud) 从JVMS:
类加载器 L 可以通过直接定义 C 或委托给另一个类加载器来创建 C。如果 L 直接创建 C,我们说 L 定义了 C,或者等价地,L 是C的定义加载器。
当一个类加载器委托给另一个类加载器时,发起加载的加载器不一定是完成加载并定义类的加载器。如果 L 通过直接定义或委托创建 C,我们说 L 启动 C 的加载,或者等价地,L 是C的启动加载器。
我对这些有点困惑。
假设我们有两个类加载器:L 和 L p,并且 L p是L的父级。
如果C被在L和用L成功创建,则L是两个限定装载机和启动加载器的C,是正确的吗?
如果 C 在 L 中定义但由 L p创建,我猜 L p正在启动C 的加载程序?
但是 C 的定义 loader 是什么?因为 C 是在 L 中定义的,但不是由它直接创建的?这是个问题。
感谢所有回复。
假设我有一个使用自定义类加载器加载的类
Class<?> clz = myClassLoader.loadClass("classLoaders.Test");
Run Code Online (Sandbox Code Playgroud)
如何在不创建实例,了解其成员或使用反射的情况下初始化类(运行其静态初始化程序)?
我遇到了一个我想了解的奇怪问题。如果有人有一个很好的解决方案,但我实际上正在寻找一种理解为什么会发生这种情况:
我写了一个自定义的 Logback 布局。我正在扩展ch.qos.logback.contrib.json.classic.JsonLayout和覆盖addCustomDataToJsonMap. 如果在日志事件参数列表中找到某种类型的参数,我想添加其他属性:
protected void addCustomDataToJsonMap(Map<String, Object> map, ILoggingEvent event) {
if (event.getArgumentArray() == null) {
return;
}
for (Object argument : event.getArgumentArray()) {
System.out.println(argument.getClass().getClassLoader()); // 1
System.out.println(JsonAttribute.class.getClassLoader()); // 2
Run Code Online (Sandbox Code Playgroud)
但是参数列表 (1) 中对象的类和静态引用一 (2) 的类由不同的类加载器加载,如输出所示:
org.springframework.boot.devtools.restart.classloader.RestartClassLoader@618157b2
sun.misc.Launcher$AppClassLoader@18b4aac2
Run Code Online (Sandbox Code Playgroud)
因此,我无法将对象强制转换为不需要的类型并访问其方法。我想到的解决方法是通过 Reflecion 访问那些,但我宁愿使用真正的价值。
我想这只是我的开发环境的问题,但正如第一部分所说,我真的很想了解发生了什么。
编辑:
正如预期的那样:在没有 spring 开发工具的“生产”模式下运行应用程序时,所有类都由同一个类加载器加载。
附录:
此函数的堆栈跟踪:
at xxx.ExtendableJsonLayout.addCustomDataToJsonMap(ExtendableJsonLayout.java:26)
at ch.qos.logback.contrib.json.classic.JsonLayout.toJsonMap(Unknown Source)
at ch.qos.logback.contrib.json.classic.JsonLayout.toJsonMap(Unknown Source)
at ch.qos.logback.contrib.json.JsonLayoutBase.doLayout(Unknown Source)
at ch.qos.logback.core.encoder.LayoutWrappingEncoder.encode(LayoutWrappingEncoder.java:115)
at ch.qos.logback.core.OutputStreamAppender.subAppend(OutputStreamAppender.java:230)
at ch.qos.logback.core.OutputStreamAppender.append(OutputStreamAppender.java:102)
at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:84)
at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:51)
at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:270)
at ch.qos.logback.classic.Logger.callAppenders(Logger.java:257)
at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:421) …Run Code Online (Sandbox Code Playgroud) ClassLoader是一个抽象类,即使它没有任何抽象方法.为什么会这样?没有抽象方法还有其他抽象类吗?
我试图从类文件动态加载.下面的代码无法调用类中的方法.
public static void main(String[] args) {
try {
File loadPath = new File("C:/loadtest/");
URL url = loadPath.toURI().toURL();
URL[] urls = new URL[]{url};
ClassLoader cl = new URLClassLoader(urls);
Class cls = cl.loadClass("TesterClass");
System.out.println("Classname: " + cls.getName());
Method[] m = cls.getMethods();
for (Method m1 : m){
try {
System.out.println("Method: " + m1.getName());
if (m1.getName().equals("getName")) {
Object o = m1.invoke(null, null);
System.out.println("o is : " + o);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
} catch (MalformedURLException | ClassNotFoundException e) …Run Code Online (Sandbox Code Playgroud) class Test {
}
public class NewClass {
public static void main(String[] args) throws ClassNotFoundException {
Test t = new Test();
String s = new String("abc");
Integer i = new Integer(1000);
System.out.println(Class.forName("Test").getClassLoader());
System.out.println(t.getClass().getClassLoader());
System.out.println(NewClass.class.getClassLoader());
System.out.println(java.lang.String.class.getClassLoader());
System.out.println(java.lang.Integer.class.getClassLoader());
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
sun.misc.Launcher$AppClassLoader@546b97fd
sun.misc.Launcher$AppClassLoader@546b97fd
sun.misc.Launcher$AppClassLoader@546b97fd
null
null
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,为什么String和Integer的类加载器为null?
是否可以在java中创建自己的自定义类加载器.如果是那么请指导我.我想在类文件中进行更改而不是类混淆,这样就无法通过任何工具进行反转