`
wu_jiaxiang
  • 浏览: 35650 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

WAS5.x 下使用 Log4j 为何没有日志输出的详细分析及解决办法

阅读更多
经常碰到有人使用了 Log4j 的项目在别处运行的好好的,一放到 WAS 下发现不能输出日志了:控制台文件 SystemOut.log 中没有 Log4j 本应输出的内容,要么就只见磁盘上有一个设定的日志文件,却总是空空如也。WebSphere 开发与应用社区hRBKe U,a.@HF
WebSphere 开发与应用社区6s0~%ez;_8d)\
本文就来以一个实际的例子分析为什么会出现这样的情况,以及告诉你应如何解决。这其中也是因为 ClassLoader 在作祟。通常我们会在通用日志框架 jakarta-commons-logging 之下使用 Log4j,这也是合情理的,因为 Struts、Hibernate 等众多框架就是这么干的,然而这却是一方面的根源。分析的过程应用了前面一篇介绍的Eclipse 远程调试 WebSphere Application Server (WAS)方法。
TdSo#tY{[d0
:h ?/t@ W.S/nt1F0测试环境和工具是:WAS 5.1+Eclipse 3.3.2+MyEclipse 6.0.1,在 Eclipse 中建立 Web  项目 testlog(此处可下载:http://www.blogjava.net/Files/Unmi/testlog.zip),其中所用到的 jar 包只有 commons-logging.jar(V1.0.3)、log4j-1.2.11.jar。再有为了知道是哪个 ClassLoader 加载了某个类,参考了:利用 JWhich 掌握类路径,确定类路径中的什么类将被载入。
%I z1e+E)C6M2Zt0WebSphere 开发与应用社区 K _hdN$gq,B9o^
项目 testlog 简介:在 WEB-INF/classes 下有两个配置文件,commons-logging.properties 和 log4j.properties。commons-logging.properties 的内容是:
CW;D-g-T\0
W v4ljW0org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.Log4jFactoryWebSphere 开发与应用社区$\6ns(uF/A&ycKeU

6Z\Xt"o)o6HI1S n0#Log4jFactory 已不推荐使用,新的建议是统一使用 LogFactoryImpl,然后由它决定声明哪个 Log 实现WebSphere 开发与应用社区?q4V4Z1C,F"K
#org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactroyImplWebSphere 开发与应用社区[ zI^7~pw Z-yj

0H&FX,W_g0log4j.properties 中配置了两个 Appender,分别输往控制台stdout(ConsoleAppender) 和 R 文件 log4j.log(DailyRollingFileAppender);输出级别设定为 DEBUG。WebSphere 开发与应用社区X/E+fb|g}m

7F$o%p+E^Q6n0日志变量 log 的声明方式是:Log log = LogFactory.getLog(TestLog.class);把该行代码放在 main 方法中是为了便于测试。该项目发布到 WAS5.1 下,通过访问 index.jsp 来进行测试,index.jsp 页面中还包括了测试日志输出和查找哪个 ClassLoader 加载了某个类的功能。WebSphere 开发与应用社区Bx@ Er
WebSphere 开发与应用社区qIk+M5Op
然后用 Eclipse 的远程调试功能连接到 WAS 的调试端口上就可以单步调试了。在 com.unmi.TestLog 类的行 Log log = LogFactory.getLog(TestLog.class); 上打断点,访问部署的 index.jsp 页面(如:http://10.80.39.41:9080/testlog/index.jsp),然后在 Log Message 框中输入信息,点击 Print Log 按钮,代码就停在 Log log = LogFactory.getLog(TestLog.class);  行上,我们真正就是从这里开始看问题了。WebSphere 开发与应用社区#Uu3S*g*c1T0WI2}
WebSphere 开发与应用社区T4T\)G+NW a.X1z
LogFactory.getLog(TestLog.class);  会调用 LogFactory.getFactory() 来获得真正的 LogFactory 实例,注意 org.apche.commons.logging.LogFactory 是个抽象类。通过看 LogFactory.getFactory() 方法代码,我们可以知道 commons-logging 是按以下顺序找到相应的 LogFactory 实现类的(详细分析见我前面写的一篇:Apache Commons Logging 是如何决定使用哪个日志实现类的)。WebSphere 开发与应用社区"|!gO(i{'rx.E2G
WebSphere 开发与应用社区&}${ ] @4AH?0L_rM
1. 从系统属性中查找键为 org.apache.commons.logging.LogFactory 的值作为 LogFactory 的实现类;却通过 System.getProperty("org.apache.commons.logging.LogFactory") 获得WebSphere 开发与应用社区JN-S`ceh
WebSphere 开发与应用社区ylN.J*Q0b h)k$ZV*r
2.  使用 JDK1.3 jar 的 Service Provider Interface(SPI) 类发现机制,从配置文件 META-INF/services/org.apache.commons.logging.LogFactory 的的第一行读取 LogFactory 的实现类名。这个 META-INF/services/org.apache.commons.logging.LogFactory 文件可以是某个 Web 应用的根目录中;也可以在 classpath 下,如某个 Jar 包中,WebRoot/WEB-INF/classes 中等。这里需多加留心下 META-INF/services/org.apache.commons.logging.LogFactory 这个目录层次及文件名。
9P4n:_.F\tr'n0
!J_ t.vpe2_,{03.  在 Classpath 下的 commons-logging.properties 文件中的,找到 org.apache.commons.logging.LogFactory 属性值作为 LogFactory 实现类WebSphere 开发与应用社区!g8ar mc!|6Vu,cl

_3d.cc,R rZok]04. 前面三步未找个 LogFactory 的实现类,或有任何异常的情况下,就用默认的实现类,即 LogFactory 为我们准备的 org.apache.commons.logging.impl.LogFactoryImplWebSphere 开发与应用社区(oNY,{N q0n)m

j2AK m/i0那么 WAS 5 是在上面哪一步先下手为强的呢?就在第三步。你是不是有疑问了,我们项目中不是有一个 commons-logging.properties 文件,在其中指定了用 Log4jFactory 的吗?可是实际用运行 WAS 加载的是 $WAS_HOME/lib/ws-commons-logging.jar!/commons-logging.properties,则其中的内容是:
"b1in'?k0WebSphere 开发与应用社区u*VL.T_/w
org.apache.commons.logging.LogFactory=com.ibm.ws.commons.logging.TrLogFactory
5Xg:x3W;e-H"l-]0
^^(p`$m*e"E3u0所以实际应用的是 WAS 5 自带的 TrLogFactory,而不是 Log4jFactory 或别的。为什么优先加载了些 commons-logging.properties 而非应用中的 commons-logging.properties,原因就是类加载器的委托机制:commons-logging.properties 是通过 ClassLoader 定位的,子 ClassLoader 加载某个类或资源时会委托给父 ClassLoader 加载,父 ClassLoader 能加载到该类或资源则优先。WebSphere 开发与应用社区G gI WU XK
WebSphere 开发与应用社区.ob/L`+~3[,?9g
应用 testlog 的类加载器 com.ibm.ws.classloader.CompoundClassLoader(从WEB-INF/class 和 WEB-INF/lib 下加载) 的父加载器是 com.ibm.ws.bootstrap.ExtClassLoader(从 $WAS_HOME/lib 下加载)。再顺带说明一下,$WAS_HOME/lib 带了 commons-logging 包 commons-logging-api.jar,它是 1.0.3版,但是 WAS 的 commons-logging-api.jar 与我们下载的 commons-logging-1.0.3.jar 相比,少了 org.apache.commons.logging.impl 包中的 Log4jFactory、Log4JCategoryLog、Log4JLogger 这几个类。所以 commons-logging 中的有些类从 WAS 的 commons-logging-api.jar 加载,有些从应用中的 commons-logging.jar 加载,以及通过不同的加载器加载的。
%[?n8P2d,U+e7|,A0WebSphere 开发与应用社区:RA`CD%u7a1q
知道了上面那些,那我们来找可能的解决办法,使我们的应用能借助 Log4j 输出日志:WebSphere 开发与应用社区b9]X.Xf"l ?
WebSphere 开发与应用社区7Sq7B3~i4u+Y
1. 修改 $WAS_HOME/lib/ws-commons-logging.jar!commons-logging.properties 的内容为:WebSphere 开发与应用社区L'E.tGa JM

j9Nz!W'uz^@ O(M0o0org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImplWebSphere 开发与应用社区7dt ]Fk8h k9W!c']
#或者org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.Log4jFactory
2D YI;Ki%C,m#zz0WebSphere 开发与应用社区?&cO'E+]E*m"V ]O3V8W
WebSphere 开发与应用社区zK+prMp*O
2. 把 $WAS_HOME/lib/ws-commons-logging.jar!/commons-logging.properties 文件删了?这样父 ClassLoader 是加载不到 commons-logging.properties,能用上应用中的 commons-logging.properties 文件,即使应用中没有 commons-logging.properties 文件也行(没有该文件时会使用 org.apache.commons.logging.impl.LogFactoryImpl,它找到了 Log4j 就用 Log4j),Log4j 也能用了。但这样做同样动了全局的东西。
@D q*^y](@0
%]QL6A7I iD03. 回到前面 LogFactory 决定具体实现类的步骤上,可以在第一、二步上做文章。其一,设置系统属性 org.apahe.commons.logging.LogFactory 为  org.apache.commons.logging.impl.LogFactoryImpl  或者为 org.apache.commons.logging.impl.Log4jFactoryWebSphere 开发与应用社区]"Ue4Ke/Ow7v
。要在 WAS 管理控制台对相应的应用服务器设置系统属性,或在程序中设定。这样做同样影响了全局,似乎不怎么妥。
a+K3lg%|CfU0
] M.V]O_04. 还有第二步,应用 SPI,指定 SERVICE_ID,具体做法是在 WebRoot/  下放个文件 META-INF/services/org.apache.commons.logging.LogFactory,在该文件的第一行写上 org.apache.commons.logging.impl.LogFactoryImpl 或是 org.apache.commons.logging.impl.Log4jFactory 就 OK 啦,这无疑是最好的办法了。总之就是不让 WAS 用 com.ibm.ws.commons.logging.TrLogFactory。因为这个文件也是通过 ClassLoader 加载的,所以 META-INF/services/org.apache.commons.logging.LogFactory 也可以放在 WebRoot/WEB-INF/classes/ 或者是你应用的某个 jar 包中。
M$?-]^n#a'@]O0
i3@&Nu)R2N1a%[ I05. 还有个办法就是直接用 Log4j,而不用或绕开 commons-logging 的 LogFactory 定位机制,直接在代码中声明使用 Log4j 的 Log,Logger log = Logger.getLogger(TestLog.class),这里的 Logger 是 org.apache.log4j.Logger。这样再换成别的日志组件就没辙了,当然很少有必要去换的。WebSphere 开发与应用社区s"h9B;V"G+h
WebSphere 开发与应用社区 i-] l AK)Ov9g9n3Q
6. 再 WAS 可以改变应用的类载入器方式。管理控制台中,在应用的属性页面,类载入器方式可以选择 PARENT_FIRST 和 PARENT_LAST,默认是 PARENT_FIRST,遵循类加载器的委托机制。若是改成 PARENT_LAST,也能让你应用中的 commons-logging.properties 优先得到加载,使用上 Log4j。真要改成 PARENT_LAST 能造成的意外情况更是不可预知的。
+M[2n,E)^y-Nm0
\o|)Pl%^6j P-x F0说到这里,记起了,有次也是因为 Log4j 未能工作,原因是某个 jar 包中有 META-INF/services/org.apache.commons.logging.LogFactory 文件。而为何只产生空的 log4j 的日志文件,应该是你哪处代码触碰到了 Log4j  的初始化行为,实际却未用上 Log4j 来输出日志。
R)o4Og)p$_:E0
Xdb G F^cx(I0这个应用放到 WAS 6.1.0.0 下 Log4j 可没什么问题,WAS 6.1.0.0 的包没有哪个有 META-INF/services/org.apache.commons.logging.LogFactory  这个文件,所以默认情况下会使用 org.apache.commons.logging.impl.LogFactoryImpl 实现类,由 LogFactoryImpl 也就能正确加载到 org.apache.commons.logging.impl.Log4JLogger。
分享到:
评论

相关推荐

    WAS上log4j日志不能输出(ibatis)sql语句解决办法[借鉴].pdf

    WAS 上 log4j 日志不能...解决 WAS 上 log4j 日志不能输出(ibatis)sql 语句的问题需要改变 WAS 的默认 LogFactory 实现类,使其使用 log4j 框架下的 LogFactory 实现类,并且需要正确配置 log4j.properties 文件。

    log4j-core-2.15.0.jar log4j-2.15.0-rc2

    Apache log4j2零日漏洞,根据 log4j-2.15.0-rc2 版本编译生成log4j-api-2.15.0.jar 1.解压你的jar jar xvf XXX.jar 2. 删除旧版本jar cd ./BOOT-INF/lib rm -rf log4j-api-*.jar 3. 上传新版本log4j-api-2.15.0....

    ga16.zip-分析GC日志native_stderr.log(可分析WAS6.1版本)

    在WebSphere Application Server(WAS)6.1版本中,GC活动会记录在特定的日志文件中,如`native_stderr.log`。这个日志文件提供了关于内存分配、垃圾收集过程以及可能的性能问题的关键信息。 **GC日志分析的重要性...

    WAS8.5.5.0升级及配置JDK1.8.docx

    ### WAS 8.5.5.0 升级至 8.5.5.13 及配置 JDK1.8 手册 #### 一、背景介绍 在 IT 领域,系统的稳定性和兼容性至关重要。随着技术的发展,软件环境也需要不断升级以满足新的需求。IBM WebSphere Application Server...

    WAS6.x结群文档及批处理

    4. **错误处理和日志记录**:为了保证批处理的健壮性,脚本中应包含错误处理机制,以及输出详细日志,便于问题排查。 以上就是关于“WAS6.x结群文档及批处理”的核心知识点。通过理解这些内容,IT管理员能够有效地...

    WAS 6.0.2.9 部署应用使用过滤器问题解决办法

    1. **日志分析**:查看WAS的日志输出,尤其是错误和警告信息,这通常能提供问题的线索。 2. **代码审查**:检查过滤器类的实现,确保它按照预期工作,没有逻辑错误或资源泄露。 3. **环境兼容性**:确认WAS 6.0.2.9...

    syslog4j-0.9.46.zip

    6. **日志记录接口**:syslog4j提供了简单的API接口,可以方便地集成到任何Java应用程序中,替代或补充现有的日志框架,如Log4j或java.util.logging。 7. **性能优化**:syslog4j考虑了性能和效率,设计了高效的...

    log4j-1.2.14.jar

    1.2.15有个Bug,会提示log4j:ERROR LogMananger.repositorySelector was null likely due to error in class reloading, using NOPLoggerRepository,大家使用1.2.14替换1.2.15即可解决!

    log4j-api-2.14.1-API文档-中英对照版.zip

    赠送jar包:log4j-api-2.14.1.jar; 赠送原API文档:log4j-api-2.14.1-javadoc.jar; 赠送源代码:log4j-api-2.14.1-sources.jar; 赠送Maven依赖信息文件:log4j-api-2.14.1.pom; 包含翻译后的API文档:log4j-api-...

    7.0.0-WS-WAS-LinuxX64-FP0000045.pak

    was7.0.45补丁was

    SQL SERVER Always On收缩日志文件详细操作及问题处理(已亲测通过)

    “The log for database 'TestDB' cannot be shrunk until all secondaries have moved past the point where the log was added.” 这个问题通常表示辅助副本(从服务器)尚未应用所有主副本上的日志记录。...

    WAS8.5静默安装及升级补丁完整步骤.docx

    WAS 8.5 静默安装及升级补丁完整步骤 WAS 8.5 静默安装是指在不需要用户交互的情况下安装 WAS 8.5。这个过程可以自动完成安装和配置WAS 8.5,减少了人工操作的错误 possibilities。下面是 WAS 8.5 静默安装的详细...

    log4j-1.2-api-2.10.0.jar

    Apache Log4j 1.x兼容性API org.apache.logging.log4j/log4j-1.2-api/2.10.0/log4j-1.2-api-2.10.0.jar

    was报错日志

    9. **日志配置**:了解如何配置WAS的日志级别和输出格式也至关重要,这有助于在出现问题时收集更详细的信息。 10. **故障排查工具**:WAS提供了若干工具,如Trace Facility、Problem Determination Tools和System ...

    WAS8.5静默安装及升级补丁.docx

    1. **准备安装源**:在描述中提到,WAS 8.5.5的安装源位于`/opt/was8.5.5/wassource`目录下,这通常包含多个zip文件,如`WAS_ND_V8.5.5_1_OF_3.zip`、`WAS_ND_V8.5.5_2_OF_3.zip`和`WAS_ND_V8.5.5_3_OF_3.zip`,这些...

    IHS无法通过80端口连接到WAS应用端口的参考解决办法

    "IHS无法通过80端口连接到WAS应用端口的参考解决办法" IHS(IBM HTTP Server)无法通过80端口连接到WAS(WebSphere Application Server)应用端口的参考解决办法是由于IHS的配置文件中缺少必要的插件文件或插件配置...

    梦幻was读取.zip

    在IT行业中,尤其是在游戏开发和数据分析领域,"梦幻西游"是一款广受欢迎的网络游戏,而"WAS"通常指的是WebSphere Application Server,这是IBM提供的一款强大的企业级应用服务器。本示例中的“梦幻was读取.zip”...

    WAS8.5.5.0升级安装补丁及配置JDK1.8.docx

    ### WAS 8.5.5.0 升级至 8.5.5.13 及配置 JDK 1.8 知识点详解 #### 一、理解 WAS 8.5.5.0 升级至 8.5.5.13 的必要性 在进行 WebSphere Application Server (WAS) 8.5.5.0 的升级前,我们需要了解为何要升级至 8.5....

    org.dom4j.jar

    当我们遇到“java.lang.ClassNotFoundException: org.dom4j.DocumentException”的错误提示时,这通常意味着系统中缺少了DOM4j库,只需将“org.dom4j.jar”添加到项目类路径中即可解决此问题。 DOM4J是基于DOM和SAX...

Global site tag (gtag.js) - Google Analytics