公司应用项目在客户部署时经常遇到此类问题,为避免实施部署时增加配置量,花了点时间找到了此问题的终极解决办法(方案二、修改org.hibernate.hql.ast.HqlLexer的源代码)。在此进行记录本问题的分析解决方案。

一、问题现象描述:

1、异常信息:

'weblogic.kernel.Default (self-tuning)']…

org.hibernate.QueryException: ClassNotFoundException: org.hibernate.hql.ast.HqlToken [

at org.hibernate.hql.ast.HqlLexer.panic(HqlLexer.java:57)

at antlr.CharScanner.setTokenObjectClass(CharScanner.java:340)

at org.hibernate.hql.ast.HqlLexer.setTokenObjectClass(HqlLexer.java:31)

at antlr.CharScanner.<init>(CharScanner.java:51)

at antlr.CharScanner.<init>(CharScanner.java:60)

at org.hibernate.hql.antlr.HqlBaseLexer.<init>(HqlBaseLexer.java:56)

at org.hibernate.hql.antlr.HqlBaseLexer.<init>(HqlBaseLexer.java:53)

at org.hibernate.hql.antlr.HqlBaseLexer.<init>(HqlBaseLexer.java:50)

at org.hibernate.hql.ast.HqlLexer.<init>(HqlLexer.java:26)

at org.hibernate.hql.ast.HqlParser.getInstance(HqlParser.java:44)

at org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:242)

atorg.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:157)

at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:111)

at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:77)

at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:56)

at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:72)

at org.hibernate.impl.SessionFactoryImpl.checkNamedQueries(SessionFactoryImpl.java:402)

at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:352)

at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1294)

2、查询weblogic安装目录下的antlr包:

3、应用中引用的是hibernate3和antlr_2.7.6的jar

二、原因分析

根据以上异常信息查看hibernate及antlr的源代码:

org.hibernate.hql.ast.HqlLexer的部分代码:

public void setTokenObjectClass(String cl) {

super.setTokenObjectClass( HqlToken.class.getName() );

}

以上super.setTokenObjectClass 方法就是antlr.CharScanner类中定义的方法:

public void setTokenObjectClass(String paramString) {

    try {

      this.tokenObjectClass = Utils.loadClass(paramString);

    } catch (ClassNotFoundException localClassNotFoundException) {

      panic("ClassNotFoundException: " + paramString);

    }

}

此方法的关键部分:Utils.loadClass(paramString);即在hibernate在解析hql是会采用此工具加载org.hibernate.hql.ast.HqlToken类(即HqlLexer类中的setTokenObjectClass方法)。此处会发生什么情况呢,请看Utils.loadClass的源代码:

  static {

  if ("true".equalsIgnoreCase(System.getProperty("ANTLR_DO_NOT_EXIT", "false")))

  useSystemExit = false;

   if ("true".equalsIgnoreCase(System.getProperty("ANTLR_USE_DIRECT_CLASS_LOADING", "false")))

  useDirectClassLoading = true;

  }

/** Thanks to Max Andersen at JBOSS and Scott Stanchfield */

public static Class loadClass(String name) throws ClassNotFoundException {

try {

ClassLoader contextClassLoader =Thread.currentThread(). getContextClassLoader();

if (!useDirectClassLoading && contextClassLoader!=null ) {

return contextClassLoader.loadClass(name);

}

return Class.forName(name);

}

catch (Exception e) {

return Class.forName(name);

}

}

从以上的代码可看处,加载org.hibernate.hql.ast.HqlToken类的类加载器是weblogic启动类加载器(不管是Thread.currentThread().getContextClassLoader()还是Class.forName,其中Class.forName采用的是Reflection.getCallerClass()的类加载器,即antlr的类加载器),并非应用类加载器。Weblogic类路径下已经存在antlr的jar包了,系统会优先使用weblogic下的antlr包,而weblogic类路径下并没有hibnate的jar包,所以在加载org.hibernate.hql.ast.HqlToken类是会抛出ClassNotFoundException: org.hibernate.hql.ast.HqlToken异常。

三、解决方案

方案一、修改weblogic类加载器中antlr加载的优先级

  1. 拷贝应用中的包antlr-2.7.6.jar到%WL_HOME%\server\lib下 
  2. 修改% mydomain%\startWebLogic.cmd(.sh) : 
    在set CLASSPATH之前加上下面一句: 
    set PRE_CLASSPATH=%WL_HOME%\server\lib\antlr-2.7.6.jar; 
    在set CLASSPATH之后加上下面一句: 
    set CLASSPATH=%PRE_CLASSPATH%;%CLASSPATH% 

此方案并不总是有效(尤其是在osgi类型项目或者同一个weblogic域下部署多个项目的情况),当然根据笔者遇到的情况成功率也在95%以上。当此方案无效时可以采用方案二。

方案二、修改org.hibernate.hql.ast.HqlLexer的源代码:

加载org.hibernate.hql.ast.HqlToken类是,直接用hibernate所在类classload加载即可:

将原来的代码:

  public
void setTokenObjectClass(String cl) {

super.setTokenObjectClass( HqlToken.class.getName() );

}

修改为:直接将hqltoken类赋值给this.tokenObjectClass

public void setTokenObjectClass(String cl) {

    this.tokenObjectClass = HqlToken.class;

}

Weblogic环境下hibernate、antlr类加载冲突问题分析及解决方案的更多相关文章

  1. 在windows环境下运行compass文件出现的错误提示解决方案

    在windows环境下运行compass文件出现的错误提示解决方案 例如:经常在项目中运行grunt命令编译scss文件的时候,会出现下面的错误提示 (Encoding::CompatibilityE ...

  2. 痞子衡嵌入式:在IAR开发环境下RT-Thread工程函数重定向失效分析

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是在IAR开发环境下RT-Thread工程函数重定向失效分析. 痞子衡旧文 <在IAR下将关键函数重定向到RAM中执行的方法> ...

  3. JNI各种环境下编译方法及初期出错分析

    转自 https://www.cnblogs.com/xyang0917/p/4172490.html 第五步.将C/C++代码编译成本地动态库文件 动态库文件名命名规则:lib+动态库文件名+后缀( ...

  4. BAE 环境下 hibernate annotations 配置

     annotations 配置 首先需要加入 hibernate-jpa-2.0-api-1.0.1.Final.jar 和 ejb3-persistence.jar 这两个包 ejb3-persis ...

  5. 在eclipse环境下使用maven install 命令碰到native2ascii-utf8问题解决方案

    报错语句:Failed to execute goal org.codehaus.mojo:native2ascii-maven-plugin:1.0-beta-1:native2ascii (nat ...

  6. win10环境下pyinstaller打包pytorch遇到的问题及解决方案

    pytorch-python源码生成windows的应用程序(.exe),报错OSError: could not get source code Failed to execute script h ...

  7. Git 常见问题 冲突原因分析及解决方案

    仅结合本人使用场景,方法可能不是最优的 1. 忽略本地修改,强制拉取远程到本地 主要是项目中的文档目录,看的时候可能多了些标注,现在远程文档更新,本地的版本已无用,可以强拉 git fetch --a ...

  8. 【Tesseract-OCR】在VS2012环境下调用API方法---注意避免名字冲突

    由于在VS2012中使用OpenCV可以得到插件ImageWatch.vsix的支持,查看图像非常方便,所以一直想在VS2012环境下把Tesseract-OCR融合进来,但是这一错误折腾了我好久: ...

  9. eclipse环境下基于已构建struts2项目整合spring+hibernate

    本文是基于已构建的struts2项目基础上整合 spring+hibernate,若读者还不熟悉struts2项目,请先阅读 eclipse环境下基于tomcat-7.0.82构建struts2项目 ...

随机推荐

  1. Ubuntu16.04+hadoop2.7.3环境搭建

    转载请注明源出处:http://www.cnblogs.com/lighten/p/6106891.html 最近开始学习大数据相关的知识,最著名的就是开源的hadoop平台了.这里记录一下目前最新版 ...

  2. Linux程序分析工具:ldd和nm

    ldd和nm是Linux下两个非常实用的程序分析工具.其中,ldd是用来分析程序运行时需要依赖的动态链接库的工具,nm是用来查看指定程序中的符号表信息的工具. 1 ldd 格式:ldd [option ...

  3. iOS中UIKit——UIStoryboard中基本知识点

    一.输出口 1.一旦在故事板中对某控件或者视图定义了输出口,不需要再在文件中对它们进行初始化.否则,会产生错误.

  4. [leetcode]_Best Time to Buy and Sell Stock I && II

    一个系列三道题,我都不会做,google之答案.过了两道,第三道看不懂,放置,稍后继续. 一.Best Time to Buy and Sell Stock I 题目:一个数组表示一支股票的价格变换. ...

  5. centos6.7下编译安装lnmp

    很多步骤不说明了,请参照本人的centos6.7下编译安装lamp,这次的架构是nginx+php-fpm一台服务器,mysql一台服务器 (1)首先编译安装nginx: 操作命令: yum -y g ...

  6. redis 配置文件解读

    # Redis 配置文件 # 当配置中需要配置内存大小时,可以使用 1k, 5GB, 4M 等类似的格式,其转换方式如下(不区分大小写) # # 1k => 1000 bytes # 1kb = ...

  7. Apache中RewriteCond规则参数介绍

    Apache中 RewriteCond语句对于我来说一直是个难点,多次试图去把它搞明白,都没有结构,这次我终于算大概知道它的意思了.RewriteCond就像我们程序中的if语句一样,表示如果符合某个 ...

  8. jquery ajax跨域请求详解

    本文章来给大家详细jquery中的ajax跨域请求, 在JQuery对于Ajax的跨域请求有两类解决方案,不过都是只支持get方式.分别是JQuery的jquery.ajax jsonp格式和jque ...

  9. PHP file_get_contents于curl性能效率比较

    说明大部分内容整理来源于网络,期待你的补充.及不当之处的纠正: 1)fopen/file_get_contents 每次请求远程URL中的数据都会重新做DNS查询,并不对DNS信息进行缓存.但是CUR ...

  10. PHP文件上传错误类型及说明

    从 PHP 4.2.0 开始,PHP 将随文件信息数组一起返回一个对应的错误代码.该代码可以在文件上传时生成的文件数组中的 error 字段中被找到,也就是 $_FILES['userfile'][' ...