更改Java类加载器的优先级(Changing the Priority of Java Classloaders)
这可能已经被问过,但如果是这样的话,我一直都找不到它。
问
Java 1.7 / 1.8中是否存在一种方法,缺少实现自定义类加载器,以使应用程序类路径比扩展类路径具有更高优先级(先前加载)?
问题
我们有一个使用Apache的log4j库的多个应用程序的平台。 我们还在[jre] / lib / ext中安装了一个自定义JCA安全提供程序,它也使用log4j。 为此,必须将log4j与提供程序一起安装在ext目录中。
平台上的一个应用程序(Apache的activemq)依赖于比提供者更老的log4j / slf4j版本。 由于提供程序的log4j jar位于[jre] / lib / ext中,它们会覆盖activemq,导致发生NoSuchMethodError:
java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log(Lorg/slf4j/Marker;Ljava/lang/String;ILjava/lang/String;Ljava/lang/Throwable;)V
那么有没有办法让应用程序类路径中的jar取代扩展目录?
再生产
您可以通过将这些jar安装到[jre] / lib / ext中来重现此问题:
- log4j的-1.2.17.jar
- SLF4J-API-1.7.2.jar
- SLF4J-log4j12-1.7.2.jar
并通过在应用程序类路径中安装这些jar:
- log4j的-1.2.14.jar
- SLF4J-API 1.5.11.jar
- SLF4J-log4j12-1.5.11.jar
并通过运行此代码:
import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import org.slf4j.LoggerFactory; import org.slf4j.spi.LocationAwareLogger; public class LogApp { public final static LocationAwareLogger logger = (LocationAwareLogger) LoggerFactory.getLogger(LogApp.class); public static void main(String[] args) throws NoSuchAlgorithmException { // Make sure custom security provider has been initialized. SecureRandom rand = SecureRandom.getInstanceStrong(); rand.doubles(); //ClassLoader cl = ClassLoader.getSystemClassLoader(); LogApp.logger.error("error: {}: {}", "string", new Exception()); LogApp.logger.log(null, LogApp.class.getCanonicalName(), logger.ERROR_INT, "some message", new Exception()); } }
哪个应该生成此错误:
Exception in thread "main" java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log(Lorg/slf4j/Marker;Ljava/lang/String;ILjava/lang/String;Ljava/lang/Throwable;)V at LogApp.main(LogApp.java:23)
回答
使用此参数运行Java:
-Xbootclasspath/p:[path_to_app_libs]/log4j-1.2.14.jar:[path_to_app_libs]/slf4j-api-1.5.11.jar:[path_to_app_libs]/slf4j-log4j12-1.5.11.jar
It's possible this has already been asked, but if so I've been unable to find it.
The Ask
Is there a way in Java 1.7/1.8, short of implementing a custom classloader, to make the application classpath higher-priority (loaded earlier) than the extension classpath?
The Issue
We have a platform with multiple apps using Apache's log4j library. We also have a custom JCA security provider installed in [jre]/lib/ext which also uses log4j. In order to do so, log4j has to be installed along with the provider in the ext directory.
One of the apps on the platform (Apache's activemq) relies on an older version of log4j/slf4j than the provider's. And since the provider's log4j jars are in [jre]/lib/ext, they override activemq's, causing a NoSuchMethodError to occur:
java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log(Lorg/slf4j/Marker;Ljava/lang/String;ILjava/lang/String;Ljava/lang/Throwable;)V
So is there a way to make the jars in the application classpath supersede the extension directory?
Reproduction
You can reproduce this issue by installing these jars into [jre]/lib/ext:
- log4j-1.2.17.jar
- slf4j-api-1.7.2.jar
- slf4j-log4j12-1.7.2.jar
And by installing these jars in the application classpath:
- log4j-1.2.14.jar
- slf4j-api-1.5.11.jar
- slf4j-log4j12-1.5.11.jar
And by running this code:
import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import org.slf4j.LoggerFactory; import org.slf4j.spi.LocationAwareLogger; public class LogApp { public final static LocationAwareLogger logger = (LocationAwareLogger) LoggerFactory.getLogger(LogApp.class); public static void main(String[] args) throws NoSuchAlgorithmException { // Make sure custom security provider has been initialized. SecureRandom rand = SecureRandom.getInstanceStrong(); rand.doubles(); //ClassLoader cl = ClassLoader.getSystemClassLoader(); LogApp.logger.error("error: {}: {}", "string", new Exception()); LogApp.logger.log(null, LogApp.class.getCanonicalName(), logger.ERROR_INT, "some message", new Exception()); } }
Which should generate this error:
Exception in thread "main" java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log(Lorg/slf4j/Marker;Ljava/lang/String;ILjava/lang/String;Ljava/lang/Throwable;)V at LogApp.main(LogApp.java:23)
Answer
Run Java with this parameter:
-Xbootclasspath/p:[path_to_app_libs]/log4j-1.2.14.jar:[path_to_app_libs]/slf4j-api-1.5.11.jar:[path_to_app_libs]/slf4j-log4j12-1.5.11.jar
原文:https://stackoverflow.com/questions/37188353
最满意答案
对于延迟发布问题的解决方案感到抱歉。
我们终于找到了一个解决方 数据作为'bytea'类型存储在数据库中
也许这是同样的情况:
所以答案是这样的:
最初的BIRT报告查询就像
SELECT t.title, t.clientServiceOrderId, t.employeeId, t.tripId, t.clientName, t.address, t.city, t.state, t.status, t.signatureImg, t.ratings ...
我们改成了
SELECT t.title, t.clientServiceOrderId, t.employeeId, t.tripId, t.clientName, t.address, t.city, t.state, t.status, encode(encode(t.signatureImg, 'escape')::bytea, 'base64') signatureImg, t.ratings, ...
这使得列
"signatureImg"
在结果中显示为"String"
数据类型。然后对于图像组件,使用onCreate方法而不是使用先前的
"expression value"
<image id="1746"> <property name="height">83px</property> <property name="width">113px</property> <method name="onCreate"><![CDATA[importPackage(Packages.javax.imageio);importPackage(Packages.java.io);importPackage(Packages.sun.misc);decoder = new BASE64Decoder();decodedBytes = decoder.decodeBuffer(this.getRowData().getColumnValue("signatureimg") == null ? "" : this.getRowData().getColumnValue("signatureimg").toString());this.data = decodedBytes;]]></method> <property name="source">expr</property> </image>
sorry for the delay in posting solution to the problem.
We finally found one solution. The data was being stored in database as a 'bytea' type
maybe this was the same case:
Postgresql, JDBC, and streaming BLOBs
so the answer was like:
The original BIRT report query was like
SELECT t.title, t.clientServiceOrderId, t.employeeId, t.tripId, t.clientName, t.address, t.city, t.state, t.status, t.signatureImg, t.ratings ...
We changed it to
SELECT t.title, t.clientServiceOrderId, t.employeeId, t.tripId, t.clientName, t.address, t.city, t.state, t.status, encode(encode(t.signatureImg, 'escape')::bytea, 'base64') signatureImg, t.ratings, ...
This made the column
"signatureImg"
appear as"String"
datatype in the result.Then for the image component, instead of using previous
"expression value"
a onCreate method was used
<image id="1746"> <property name="height">83px</property> <property name="width">113px</property> <method name="onCreate"><![CDATA[importPackage(Packages.javax.imageio);importPackage(Packages.java.io);importPackage(Packages.sun.misc);decoder = new BASE64Decoder();decodedBytes = decoder.decodeBuffer(this.getRowData().getColumnValue("signatureimg") == null ? "" : this.getRowData().getColumnValue("signatureimg").toString());this.data = decodedBytes;]]></method> <property name="source">expr</property> </image>
相关问答
更多-
事实证明,我在Tomcat的lib/文件夹中有另一个JDBC驱动程序,除了WEB-INF/lib/ 。 删除Tomcat的一个解决了我的问题。 (是的,这是一个不同的类加载器问题,感谢@NathanHughes。) Turns out, I had another JDBC driver in my Tomcat's lib/ folder, apart from the one in WEB-INF/lib/. Removing the Tomcat's one fixed my problem. (Ye ...
-
你没有提供太多的信息。 什么类型的控制? 有嵌套的东西吗? 屏幕截图怎么样? 您提到尝试通过“选择一些选项”来解决它,在尝试诊断问题时不是很有帮助。 我唯一可以建议的是取消选中Page Break选项卡中的“Repeat Header”复选框。 You are not giving very much information to go on. What type of control? Is there anything nested? How about a Screen shot? You menti ...
-
对于延迟发布问题的解决方案感到抱歉。 我们终于找到了一个解决方 数据作为'bytea'类型存储在数据库中 也许这是同样的情况: Postgresql,JDBC和流式BLOB 所以答案是这样的: 最初的BIRT报告查询就像 SELECT t.title, t.clientServiceOrderId, t.employeeId, t.tripId, t.clientName, t.address, t.city, t.state, t.status, t.signatureImg, t.ratings ... ...
-
我设法找到了问题。 在表中数据集绑定到我没有任何分组。 添加分组后,Maximo和BIRT设计器预览中都会显示多个页面。 I managed to find the problem. In the table the dataset was bound to I didn't have any grouping. Once the grouping was added the multiple pages were displaying on both Maximo and BIRT designer pr ...
-
检查您是否已在连接字符串中正确配置了PostgreSQL服务器的URL。 还要检查PostgreSQL服务器的版本以及您正在使用的JDBC驱动程序的版本。 Check that you have correctly configured your URL in your connection string to the PostgreSQL server. Also check the version of the PostgreSQL server and that of the JDBC driver ...
-
我认为你的POJO在Tomcat中不起作用,因为你忘了为BIRT引擎提供一个类加载器。 尝试添加: import org.eclipse.birt.report.engine.api.EngineConstants; 并在您的构造函数中: config.getAppContext().put(EngineConstants.APPCONTEXT_CLASSLOADER_KEY, BirtRenderer.class.getClassLoader()); Ok, I found a problem. Th ...
-
有关如何在Java应用程序中集成BIRT,请先阅读Report Engine API BIRT还提供了一个用于创建报告模板的API。 请参阅Design Engine API For how to integrate BIRT in a Java application start with reading Report Engine API BIRT also provides an API to create report templates. See Design Engine API
-
正如Mark所说,没有必要将org.eclipse.birt.ojdbc作为依赖项添加。 我停止使用org.eclipse.birt.report.data.oda.jdbc_4.6.0.v201606072122.jar并使用我的本地ojdbc驱动程序。
com.oracle ojdbc6 11.2.0.4.0 在BIRT开源中保存报告(Save report in BIRT open source)[2022-01-19]
您不需要编写任何代码。 有两个简单的选择, 您的人可以使用“打开方式”打开.rptdesign并选择,记事本,写字板,(甚至是网络浏览器; IE,FF) 你用记事本(等)打开.rptdesign并保存为.txt(或任何你想要的),然后将它作为文本文档打开。 如果它保存为.rptdesign并使用文本编辑器打开; 可以进行更改并保存为.rptdesign,BIRT将打开并运行报告(假设更改正常)。 You don't need to write any code. There are two easy opt ...使用birt引擎生成报告时出现FontHandler异常(FontHandler exception during report generation with birt engine)[2022-07-22]
尝试: 将您的字体目录添加到CLASSPATH(或将/ symlink报告字体复制到CLASSPATH中的任何目录) 使用以下代码注册字体目录: import java.security.AccessController; import java.security.PrivilegedAction; import com.lowagie.text.FontFactory; ... AccessController.doPrivileged(new PrivilegedAction相关文章
更多最新问答
更多- h2元素推动其他h2和div。(h2 element pushing other h2 and div down. two divs, two headers, and they're wrapped within a parent div)
- 创建一个功能(Create a function)
- 我投了份简历,是电脑编程方面的学徒,面试时说要培训三个月,前面
- PDO语句不显示获取的结果(PDOstatement not displaying fetched results)
- Qt冻结循环的原因?(Qt freezing cause of the loop?)
- TableView重复youtube-api结果(TableView Repeating youtube-api result)
- 如何使用自由职业者帐户登录我的php网站?(How can I login into my php website using freelancer account? [closed])
- SQL Server 2014版本支持的最大数据库数(Maximum number of databases supported by SQL Server 2014 editions)
- 我如何获得DynamicJasper 3.1.2(或更高版本)的Maven仓库?(How do I get the maven repository for DynamicJasper 3.1.2 (or higher)?)
- 以编程方式创建UITableView(Creating a UITableView Programmatically)
- 如何打破按钮上的生命周期循环(How to break do-while loop on button)
- C#使用EF访问MVC上的部分类的自定义属性(C# access custom attributes of a partial class on MVC with EF)
- 如何获得facebook app的publish_stream权限?(How to get publish_stream permissions for facebook app?)
- 如何防止调用冗余函数的postgres视图(how to prevent postgres views calling redundant functions)
- Sql Server在欧洲获取当前日期时间(Sql Server get current date time in Europe)
- 设置kotlin扩展名(Setting a kotlin extension)
- 如何并排放置两个元件?(How to position two elements side by side?)
- 如何在vim中启用python3?(How to enable python3 in vim?)
- 在MySQL和/或多列中使用多个表用于Rails应用程序(Using multiple tables in MySQL and/or multiple columns for a Rails application)
- 如何隐藏谷歌地图上的登录按钮?(How to hide the Sign in button from Google maps?)
- Mysql左连接旋转90°表(Mysql Left join rotate 90° table)
- dedecms如何安装?
- 在哪儿学计算机最好?
- 学php哪个的书 最好,本人菜鸟
- 触摸时不要突出显示表格视图行(Do not highlight table view row when touched)
- 如何覆盖错误堆栈getter(How to override Error stack getter)
- 带有ImageMagick和许多图像的GIF动画(GIF animation with ImageMagick and many images)
- USSD INTERFACE - > java web应用程序通信(USSD INTERFACE -> java web app communication)
- 电脑高中毕业学习去哪里培训
- 正则表达式验证SMTP响应(Regex to validate SMTP Responses)