是否可以为javac(或某些替代java编译器)指定自定义类加载器?
我喜欢这样的壮举,因为它允许我编译使用只能由我的特殊类加载器找到的类的类.
对于好奇的:我会编写一个连接到数据库的类,并根据它找到的表创建类.
考虑这段代码(完全基于飞碟的"入门"代码,保留其权利):
package flyingsaucerpdf;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import org.xhtmlrenderer.pdf.ITextRenderer;
public class PDFMaker {
public static void main(String[] args) throws Exception {
new PDFMaker().go();
}
public void go() throws Exception {
String inputFile = "sample.html";
String url = new File(inputFile).toURI().toURL().toString();
String outputFile = "firstdoc.pdf";
OutputStream os = new FileOutputStream(outputFile);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(url);
renderer.layout();
renderer.createPDF(os);
os.close();
}
}
Run Code Online (Sandbox Code Playgroud)
几个事实:
Caused by: org.w3c.dom.DOMException: NAMESPACE_ERR: An attempt is made to create or change an object in …
我想知道,我已经尝试了无数令人费解的搜索术语来确定是否有办法延迟Java中的类加载.我的意思是,类可以在类/构建路径上找到,但我不希望它们在发布时加载.这导致使用错误的类加载器.
我是否可以选择性地延迟或阻止默认类加载器加载某些类/ JAR?
示例(在构建路径上使用第三方jar):
// boilerplate main
JarWrapper apiJar = SpecialJarLoader("api.jar"); // SpecialJarLoader is a proprietary class loader
Class apiClass = apiJar.loadClass("org.company.comm.AConnection"); // runtime failure here due to the class already being loaded
Run Code Online (Sandbox Code Playgroud)
如果我从构建路径中删除Jar,apiClass.getClassLoader()是预期的专有加载器.问题是我无法自由使用"org.company.comm.AConnection"或Jar中的任何其他类(包括IDE的自动完成),因为它实际上并不在构建路径上.
我想在Tomcat6中自定义我的日志消息,并创建了一个类"MyFormatter",如下所示:
public class LogFormatter extends Formatter {
@Override
public String format(LogRecord record) {
StringBuilder sb = new StringBuilder();
sb.append("LOLCAT--")
.append(new Date(record.getMillis()))
.append(" \t")
.append(record.getThreadID())
.append(" \t")
.append(record.getSourceMethodName())
.append(" \t")
.append(record.getSourceClassName())
.append(" \t")
.append(record.getLevel().getLocalizedName())
.append(": ")
.append(formatMessage(record))
.append(System.getProperty("line.separator"));
return sb.toString();
}
}
Run Code Online (Sandbox Code Playgroud)
我把它打包成一个.jar并放在$ {catalina.home}/lib中.
在我的logging.properties文件中,我添加了以下内容:
1catalina.org.apache.juli.FileHandler.level = FINE
1catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
1catalina.org.apache.juli.FileHandler.prefix = lolcat.
1catalina.org.apache.juli.FileHandler.formatter = my.package.LogFormatter
Run Code Online (Sandbox Code Playgroud)
在尝试不同的包装,不同的配置后,我决定尝试内置的"org.apache.juli.OneLineFormatter" - 这完美地运作.所以配置应该没问题.
问题依然存在,为什么Tomcat6加载我的类?
我正在将应用程序迁移到JBoss 7,其中所有依赖项都在"JBOSS_HOME/server/default/lib"(JBoss 4)中.我包含了lib "servlet.jar"(javax.servlet.*),但是,在设置了JBoss 7的全局模块(modules.xml,standalone.xml,war文件中的jboss-deployment-structure.xml)后,JBoss正常加载了库.
当JBoss 7尝试启动过滤器时,我得到以下异常:
15:09:15,222 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/RegistrarValorDolar]] (MSC service thread 1-2) Exception starting filter cripto: java.lang.ClassCastException: cenpra.com.sigtec.business.utilities.SessionFilter cannot be cast to javax.servlet.Filter
at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:441) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:3269) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardContext.start(StandardContext.java:3865) [jbossweb-7.0.13.Final.jar:]
at org.jboss.as.web.deployment.WebDeploymentService.start(WebDeploymentService.java:90) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [rt.jar:1.7.0_15]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [rt.jar:1.7.0_15]
at java.lang.Thread.run(Unknown Source) [rt.jar:1.7.0_15]
Run Code Online (Sandbox Code Playgroud)
试图删除从全球模块库"的servlet.jar",在尝试了服务器负载是通过内部的jar自己的类,我得到了ClassNotFoundException的javax.servlet.Filter类.
有没有办法从字节数组创建URL?我有一个自定义类加载器,它存储来自存储条目名称及其字节的HashMap中JarInputStream的所有条目.我想要从字节数组创建一个URL的原因是为了满足ClassLoaders中的getResource(String name)方法.我已经使用ByteArrayInputStream完成了getResourceAsStream(String name).
给定班级 org.popper.example.pages.Login
@Page(name="Login")
public interface Login {
}
Run Code Online (Sandbox Code Playgroud)
导出到c:\pos\example.jar以下servlet
public class PopperServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public static void main(String[] args) throws MalformedURLException, ClassNotFoundException {
URLClassLoader ucl = new URLClassLoader(new URL[] {new File("c:/pos/example.jar").toURI().toURL()});
System.out.println(Arrays.asList(ucl.loadClass("org.popper.example.pages.Login").getAnnotations()));
}
public PopperServlet() throws MalformedURLException, ClassNotFoundException {
URLClassLoader ucl = new URLClassLoader(new URL[] {new File("c:/pos/example.jar").toURI().toURL()});
System.out.println(Arrays.asList(ucl.loadClass("org.popper.example.pages.Login").getAnnotations()));
}
}
Run Code Online (Sandbox Code Playgroud)
以main身份运行代码可显示预期结果
[@org.popper.fw.annotations.Page(name=Login)]
Run Code Online (Sandbox Code Playgroud)
在Tomcat中将代码作为servlet运行无法找到注释
[]
Run Code Online (Sandbox Code Playgroud)
谁能告诉我为什么?
它在这里说,所有Web应用程序都可以看到通用的类加载器.那么在WEB-INF/lib我的war应用程序的文件夹中有一个JAR文件和在Tomcat的lib文件夹中有相同的JAR文件之间的区别是什么?
这个JAR是我创建的Java SPI的提供者.当我拥有它时WEB-INF/lib,一切都很完美.但是,如果我尝试将此JAR放在Tomcat的lib文件夹下(或在shared/lib配置它之后catalina.properties),我会收到错误.第二个选项对我来说更好,因为我需要完全解耦我的应用程序和提供程序.
我得到的错误是ClassNotFoundException代表我的服务的接口(JAR实现的).此接口位于第三个项目中,该项目是我的war应用程序的依赖项.
我正在使用org.apache.commons.lang.SerializationUtils,但是我收到了一个错误.如果您需要更多信息我是Java新手,请告诉我代码:
Profile profile2 = new Profile();
profile2.setFileName(path);
profile2.setStatus("UPLOADED");
byte[] payload2 = SerializationUtils.serialize(profile2);
profile = (Profile) SerializationUtils.deserialize(payload2);
Run Code Online (Sandbox Code Playgroud)
运行时错误输出:
org.apache.commons.lang.SerializationException: java.lang.ClassNotFoundException: com.xxx.xxx.Profile
at org.apache.commons.lang.SerializationUtils.deserialize(SerializationUtils.java:166)
at org.apache.commons.lang.SerializationUtils.deserialize(SerializationUtils.java:193)
Run Code Online (Sandbox Code Playgroud)
人们说Profile不在classpath中.如果确实如此,则会在"new Profile()"上发生错误.我对吗?
我找到了一个解决方法:
profile = (EveSuccessCriteriaProfile) SerializationUtils.deserialize(payload2);
Run Code Online (Sandbox Code Playgroud)
取而代之
InputStream fis = null;
fis = new ByteArrayInputStream(payload2);
ObjectInputStream o = new ObjectInputStream(fis);
profile = (Profile) o.readObject();
Run Code Online (Sandbox Code Playgroud)
它工作正常
当我创建自己的String类时.如果在同一个包中有另一个类,main(String [] args)似乎选择我的String类而不是rt.jar中的类.我的问题是,为什么在这种情况下,Bootstrap类加载器不会选择rt.jar中的String类.我的理解是一个类加载请求来到Application loader将被委托给bootstrap类加载器.