META-INF/MANIFEST.MF文件中Sealed头的作用与含义
政府某部门想打造一个国产软件平台,从硬件服务器、操作系统、数据库、应用服务器中间件等全部采用国产平台,并将一个运行良好的应用软件进行改造,以适应国产数据库与原Oracle数据库在SQL语句、系统函数等方面的不同。
apusic应用服务器作为国产应用服务器中间件参与了移植测试和压力测试工作。首先跟应用软件开发商基于oracle数据库做了移植测试,从weblogic平台移植到了apusic应用服务器,实现apusic + oracle运行正常。
然后跟国产数据库做移植测试,国产数据库采用gbase。应用软件用到了hibernate2作为数据持久工具,由于hibernate没有内置对gbase的dialect支持,gbase厂商自己写了一个类,命名为net.sf.hibernate.dialect.GBaseDialect,并打包成gbase_dialect.jar,放到了应用软件的lib文件夹下。
然后启动apusic应用服务器时报错:
net.sf.hibernate.MappingException: could not instantiate id generator at net.sf.hibernate.id.IdentifierGeneratorFactory.create(IdentifierGeneratorFactory.java:82) at net.sf.hibernate.mapping.SimpleValue.createIdentifierGenerator(SimpleValue.java:82) at net.sf.hibernate.persister.AbstractEntityPersister.<init>(AbstractEntityPersister.java:630) at net.sf.hibernate.persister.EntityPersister.<init>(EntityPersister.java:716) at net.sf.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:42) at net.sf.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:137) at net.sf.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:768) at com.lbs.commons.op.HibernateSession.currentSession(HibernateSession.java:32) at com.lbs.commons.op.OPManager.query(OPManager.java:159) at com.lbs.cp.plugin.CodeListPlugIn.init(CodeListPlugIn.java:59) at org.apache.struts.action.ActionServlet.initModulePlugIns(ActionServlet.java:1158) at org.apache.struts.action.ActionServlet.init(ActionServlet.java:473) at javax.servlet.GenericServlet.init(GenericServlet.java:215) at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1053) at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:955) at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4035) at org.apache.catalina.core.StandardContext.start(StandardContext.java:4338) at com.cvicse.inforsuite.webContainer.GeronimoStandardContext.access$201(GeronimoStandardContext.java:60) at com.cvicse.inforsuite.webContainer.GeronimoStandardContext$SystemMethodValve.invoke(GeronimoStandardContext.java:343)……//此处略去部分异常信息Caused by: net.sf.hibernate.MappingException: Dialect does not support sequences at net.sf.hibernate.dialect.Dialect.getSequenceNextValString(Dialect.java:319) at net.sf.hibernate.id.SequenceGenerator.configure(SequenceGenerator.java:62) at net.sf.hibernate.id.IdentifierGeneratorFactory.create(IdentifierGeneratorFactory.java:78) ... 83 more
貌似是Dialect不支持sequences(getSequenceNextValString()),可是gbase厂商提供的类里有对序列的支持。
后来在测试中发现,即使从应用的lib中删除gbase的gbase_dialect.jar,仍然报同样的错误,说明这个jar根本没有加载。
由于gbase的gbase_dialect.jar中,GBaseDialect类所在的包为net.sf.hibernate.dialect,跟hibernate提供的其他数据库的dialect包名一致,所以将gbase提供的GBaseDialect类打包在了hibernate2.jar中,跟hibernate提供的其他数据库的dialect在一个jar中,删除gbase_dialect.jar,这时启动apusic正常。
据此判断,net.sf.hibernate.dialect.GBaseDialect类文件本身没有问题,gbase提供的gbase_dialect.jar中,除了这个类文件外,就只有META-INF下MANIFEST.MF文件,所以怀疑是这个文件有问题。打开这个文件,只有两行内容:
Manifest-Version: 1.0
Sealed:true
将gbase_dialect.jar中META-INF下MANIFEST.MF文件Sealed:true去掉,重新打包,放到应用lib下,将先前打包进hibernate2.jar的GBaseDialect类删除,重启apusic,终于正常。
到网上搜索关于Sealed:true,找到如下资料:
public String getSequenceNextValString(String sequenceName) throws MappingException { throw new MappingException("Dialect does not support sequences"); }
将gbase打包时Sealed: true去掉,则JVM可以顺利找到gbase的net.sf.hibernate.dialect.GBaseDialect。