我有一个有趣的问题,在运行时没有找到org.apache.log4j.Logger类.我正在尝试获得授权,这就是它失败的地方:
OAuthAuthorizer oauthAuthorizer = new OAuthAuthorizer(OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET, SAML_PROVIDER_ID, userId);
我正在使用JDeveloper 11.1.1.6.这就是我所知道的:
我查看了我的UI.war/WEB-INF/lib目录,我看到了log4j-1.2.17.jar.
抱怨它的类是org.opensaml.xml.XMLConfigurator
Caused by: java.lang.NoClassDefFoundError: org/apache/log4j/Logger
at org.opensaml.xml.XMLConfigurator.<clinit>(XMLConfigurator.java:60)
at org.opensaml.DefaultBootstrap.initializeXMLTooling(DefaultBootstrap.java:195)
at org.opensaml.DefaultBootstrap.bootstrap(DefaultBootstrap.java:91)
at com.intuit.ipp.aggcat.util.SAML2AssertionGenerator.getSAMLBuilder(SAML2AssertionGenerator.java:156)
at com.intuit.ipp.aggcat.util.SAML2AssertionGenerator.createSubject(SAML2AssertionGenerator.java:187)
at com.intuit.ipp.aggcat.util.SAML2AssertionGenerator.buildAssertion(SAML2AssertionGenerator.java:114)
at com.intuit.ipp.aggcat.util.SAML2AssertionGenerator.generateSignedAssertion(SAML2AssertionGenerator.java:83)
at com.intuit.ipp.aggcat.util.SamlUtil.createSignedSAMLPayload(SamlUtil.java:156)
at com.intuit.ipp.aggcat.util.OAuthUtil.getOAuthTokens(OAuthUtil.java:60)
at com.intuit.ipp.aggcat.core.OAuthAuthorizer.<init>(OAuthAuthorizer.java:85)
at com.incomemax.view.intuit.WebUtil.getAggCatService(WebUtil.java:91)
Run Code Online (Sandbox Code Playgroud)
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Logger
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:305)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:246)
... 64 more
Run Code Online (Sandbox Code Playgroud)我解压缩了XMLConfigurator,奇怪的是它没有导入org.apache.log4j.Logger它使用org.slf4j.Logger,它也在我的jars目录中(slf4j-api-1.7.5.jar).同样有趣的是,第60行(参见堆栈跟踪)是我的反编译中的空行.
当然,如果我在设计时添加Logger.xxxxx,它会发现它很好.
我直接从示例java代码中使用代码/ jar,但导入到我现有的应用程序中.
我一直在网上寻找答案,我相信我已经检查了所有我能想到的领域.我也引用了这个非常好的页面:http://myarch.com/classnotfound/
鉴于授权是使用Intuit Developer API的第1步,我有点卡住了.
从@jhadesdev建议中添加输出:
所有版本的log4j Logger:
从OAuthAuthorizer类的类加载器可以看到所有版本的log4j:
所有版本的XMLConfigurator:
罐子:文件:/ …
是否可以知道是否已加载Java类而不尝试加载它?Class.forName试图加载该类,但我不希望这种副作用.还有另外一种方法吗?
(我不想覆盖类加载器.我正在寻找一种相对简单的方法.)
出于调试原因和好奇心,我希望列出加载到特定类加载器的所有类.
看到类加载器的大多数方法都受到保护,实现我想要的最佳方法是什么?
谢谢!
最近遇到了一些让我思考的代码.有什么区别:
Class theClass = Class.forName("SomeImpl");
SomeImpl impl = (SomeImpl)theClass.newInstance();
Run Code Online (Sandbox Code Playgroud)
和:
Class theClass = ClassLoader.loadClass("SomeImpl");
SomeImpl impl = (SomeImpl)theClass.newInstance();
Run Code Online (Sandbox Code Playgroud)
他们是同义词吗?在某些情况下,是否优先于另一方?使用这两种方法有什么用,有什么用呢?
提前致谢.
最近,我切换到Java 11并开始调试应用程序,并看到以下消息:
OpenJDK 64位服务器VM警告:引导加载程序类仅支持共享,因为已附加了引导程序类路径
我需要担心吗?
任何人都可以解释从Tomcat中的lib目录加载jar文件的顺序吗?是字母的吗?随机?还是其他一些订单?
在具有多个ClassLoader的环境中使用ServiceLoader的最佳实践是什么?文档建议在初始化时创建并保存单个服务实例:
private static ServiceLoader<CodecSet> codecSetLoader = ServiceLoader.load(CodecSet.class);
Run Code Online (Sandbox Code Playgroud)
这将使用当前上下文类加载器初始化ServiceLoader.现在假设此片段包含在使用Web容器中的共享类加载器加载的类中,并且多个Web应用程序想要定义自己的服务实现.这些不会在上面的代码中被提取,甚至可能使用第一个webapps上下文类加载器初始化加载器并向其他用户提供错误的实现.
始终创建新的ServiceLoader似乎是浪费性能,因为它必须每次枚举和解析服务文件.编辑:这甚至可能是一个很大的性能问题,如关于java的XPath实现的答案所示.
其他库如何处理这个?他们是否为每个类加载器缓存实现,他们是否每次都重新分析它们的配置,还是只是忽略了这个问题而只适用于一个类加载器?
我已经阅读了很多关于Java类加载器的内容,但到目前为止我还没有找到这个简单问题的答案:
我在jars v1.jar和v2.jar中有两个版本的com.abc.Hello.class.我想在我的应用程序中使用它们.这样做最简单的方法是什么?
我不希望那么简单,但沿着这些方向的东西会很棒:
Classloader myClassLoader = [magic that includes v1.jar and ignores v2.jar]
Hello hello = myclassLoader.load[com.abc.Hello]
Run Code Online (Sandbox Code Playgroud)
而在另一个班级:
Classloader myClassLoader = [magic that includes v2.jar and ignores v1.jar]
Hello hello = myclassLoader.load[com.abc.Hello]
Run Code Online (Sandbox Code Playgroud)
我想避免使用OSGi.
我有一些调用的代码..
x = getClass().getClassLoader();
Run Code Online (Sandbox Code Playgroud)
这会返回null.
当我从Eclipse启动相同的代码而不是命令行时,它返回一个类加载器.
我可以破解代码来做到这一点......
if (getClass().getClassLoader() == null)
{
x = ClassLoader.getSystemClassLoader().getSystemResourceAsStream( loadedPropFileName );
}
Run Code Online (Sandbox Code Playgroud)
两者都使用相同的JVM进行编译和运行.(我99.99%肯定).
任何人都有任何想法为什么第一个将为类加载器返回null?
编辑:
我的问题是"任何人都有任何想法为什么同一个类在从Eclipse启动时返回null,从命令行加载时是类加载器."
感谢Bootstap加载器必须在Eclipse中加载类的建议.我不知道为什么会这样.
我想创建一个父/ last/child-first类加载器,例如一个类加载器,它首先在子类loder中查找类,然后只委托它的父ClassLoader来搜索类.
澄清:
现在我知道,要得到完整的类加载分离-我需要使用像传递null,因为它是父的URLClassLoader,归功于这个回答我刚才的问题
但是,当前的问题来帮我解决这个问题:
我的代码+依赖jar正被加载到现有系统中,使用ClassLoader将System的ClassLoader设置为它的父级(URLClassLoader)
该系统使用的某些库与我需要的版本不兼容(例如,旧版本的Xerces,不允许我运行我的代码)
如果运行独立,我的代码运行完全正常,但如果从该ClassLoader运行则它会失败
Howerver我确实需要访问父ClassLoader中的许多其他类
因此,我想允许我使用自己的Override,父类加载器"jars":如果在子类加载器中找到我调用的类(例如,我提供了一个带有我自己的jar的更新版本的Xerces,而不是一个用户由加载我的代码和jar的ClassLoader.
这是加载我的代码+ Jars的系统代码(我无法更改此代码)
File addOnFolder = new File("/addOns");
URL url = addOnFolder.toURL();
URL[] urls = new URL[]{url};
ClassLoader parent = getClass().getClassLoader();
cl = URLClassLoader.newInstance(urls, parent);
Run Code Online (Sandbox Code Playgroud)
这是"我的"代码(完全取自Flying Sauser"Hello World"代码演示):
package flyingsaucerpdf;
import java.io.*;
import com.lowagie.text.DocumentException;
import org.xhtmlrenderer.pdf.ITextRenderer;
public class FirstDoc {
public static void main(String[] args)
throws IOException, DocumentException {
String f = new File("sample.xhtml").getAbsolutePath();
System.out.println(f);
//if(true) return;
String inputFile = "sample.html";
String url = new File(inputFile).toURI().toURL().toString();
String outputFile = …Run Code Online (Sandbox Code Playgroud)