Q: 引起NoClassDefFoundError的原因?
A: J2EE容器中引发NoClassDefFoundErrors最常见的原因是父类加载器使用了只在子类加载器中有效的类;例如,一个在$CLASSPATH中的扩展类只能在子类加载器中有效。幻灯片里还有深入的调试技巧。
Q:如果在你的system/lib文件夹和WAR里同时都有一个jar包,那么哪一个具有较高的优先级?
A:默认的情况下,Java类加载器是“parent-first”,是指它会首先请求它的父加载器来加载,只有在父加载器无法加载的时候才试图自己加载。因此如果$CLASSPATH中有这个类,那么它将是应用类加载器的首选。
WebLogic
Server的weblogic.xml中有一个选项prefer-web-inf-classes,可以将war中类库设置成优先加载。必须要小心的设
置这个选项。一旦设置了这个,会很容易导致ClassCastExceptions和其它无法预测的类加载问题
Q:当线程池里的线程被分配到不同应用的进程时,它们是怎样取的不同类加载器层次的?
A: WebLogic Server在应用程序部署的时候创建类加载器。当容器在响应请求的时候,它需要保证这个请求被分发到了正确的应用程序类加载器。
Q:在调试的时候能够设置端点吗?
A: 是的!BEA WebLogic Workshop是一个支持端点的Java调试器。其它支持端点的Java调试器或IDE也能够正常的运行。
Q: APP-INF是标准J2EE的一部分,还是WebLogic Server的特性?
A: APP-INF是一个由BEA增加的特性,目前还没有添加到J2EE标准中。但是,将有APP-INF的应用转移到其它不支持APP-INF的老版本WLS或其它容器也是非常得容易。
你可以通过manifest class-path来将应用转移到其它老的WLS版本上。推荐的方式是在产生目标文件的时候生成方便的ear文件。生产目标文件的时候会产生一个manifest文件,这个文件里有对APP-INF/lib中所有jar文件的manifest class-path 索引。每一个J2EE模块都需要这个manifest文件。
Q:哪里可以找到wlpackage/wlcompile命令?这些是命令行命令吗?能不能在WebLogic Admin Server Console里使用?
A: wlpackage 和 wlcompile都是ant任务。Ant的执行程序在weblogic.jar 中。同WebLogic platform打包在一起的ant 有一个属性文件,这个文件包含了所以事先定义好的BEA taskdefs。
如果你使用的是不同版本的ant,你需要手工来使用这些taskdefs。以下是一些在BEA ant 属性文件中定义的任务名称和类名:
ddinit=weblogic.ant.taskdefs.ejb.DDInit
wldeploy=weblogic.ant.taskdefs.management.WLDeploy
wlserver=weblogic.ant.taskdefs.management.WLServer
wlconfig=weblogic.ant.taskdefs.management.WLConfig
wlcompile=weblogic.ant.taskdefs.build.WLCompileTask
wlpackage=weblogic.ant.taskdefs.build.WLPackageTask
wlappc=weblogic.ant.taskdefs.j2ee.Appc
Q: 我需要在开发模式中频繁的更换Java类,在更改之后是不是要重新部署整个应用程序?
A: 这取决于Java类是在哪里被加载的。如果类是在$CLASSPATH当中,就需要重新启动server。如果类是在你的应用程序当中,就只需要重新部署应用。如果类在webapp中,就只需要重新部署webapp,而不需要重新部署整个app了。
是否需要重新部署和类加载器的结构有关,幻灯片里有一张类加载器结构图。如果你改动了父类加载器加载的某些类,你需要重新部署由子类加载器加载的所有东西。
Q: 在使用wlappc的时候,提示说不认识wlappc这个任务。是不是我缺少什么东西或步骤?
A: 请参考前面的问答。你硕使用的ant和BEA打包的ant版本不一致,因此你需要为wlappc包含一个taskdef。参考如下的方式:
<taskdef name="wlappc"
classname="weblogic.ant.taskdefs.j2ee.Appc"
/>
Q: ant中有停止WebLogic cluster的任务吗?比如<wlserver>。我需要指定停止一个cluster并重新部署。
A: wlserver任务可以用来停止server。只需要把参数action设置成“shutdown”就可以了
Q:
有些时候我们从support那里取得临时的补丁(CR####.jar),在classpath中将它们放在weblogic.jar之前。但是如果
weblogic.jar在应用程序的build classpath中,需不需要修改build文件来引用CR jar文件?
A: 是的,建议你也在build classpath中包含进补丁。这些补丁可能修复了像weblogic.appc或weblogic.ejbc这样的工具,它们可能会在你build工程的时候使用到。
Q: 管理和打包部署描述符(从单机开发模式到集群产品模式)的最好方式是什么?
A: 问题关键在于描述符里绑定的是些什么。例如,你的描述符里可能引用了http://test:7001,但是在生产模式下应该是http://production:7001
我的建议是在描述符里包含一些变量,然后使用像sed、perl这样的预处理程序来将这些变量替换成合适的值。例如,你的描述符里可能有$SERVER,用sed生成一个test描述符,这个描述符里$SERVER被替换成了test URL。
Q: 在一个WebLogic域中同时部署Workshop-enabled的应用和non-Workshop-enabled的应用是否可以?
A: 在同一个server或者域中运行这两类应用程序是没有问题的。是否在同一个WLS实例中运行多个应用取决于end-user的需要。分离开应用的话,可以取的更好的独立性,但是需要管理多个server。
Q:协同定位(co-location)是默认的设置还是需要在某个地方手工配置?
A:这个没有默认的设置。应用都被部署到集群或者服务器上。如果将应用程序拆分成两部分部署到两个地方,则是“split”;如果统一部署到一层,则是“co-located”。
Q: 两个不同的WebLogic Server的license能否被同一个server使用,用来创建两个使用同样端口但环境不同的domain?
A:这个我不太清楚。关于license的问题,你可以E-mail:support@bea.com 咨询
Q: 我们的启动类使用到了EJB,因此我需要在classpath中加入EJB的接口类,有没有什么方法可以避免这种依赖?
A:
启动类是在server启动的时候被调用的。部署应用程序的时候,Application范围的监听器会收到callback。如果能够等到部署完成,你
就可以使用ApplicationLifecycleListener或者servlet
listener了。监听器里能够使用classloader,就可以不用在classpath里面加入EJB接口类了。
Q: WebLogic是否提供了这样的API或机制?当集群里最后一个机器宕机(无论是否正常情况)的时候,可以执行一个自定义的任务,这样我们就可以做些清理工作。
A: 我不知道有这样一种API。每个server正常关闭的时候你都会收到一个hook,而如果程序崩溃,则不会。
Q: 因为每个JSP文件会被一个单独的类加载器加载,那么访问JSP是不是要慢一些或者不够memory-efficient?那对于Servlet呢?使用的是哪一个类加载器?
A: 一个webapp中的所有servlet都是被一个普通的类加载器加载的。JSP是有一个单独的类加载器加载,它的父加载器是webapp的加载器。
WLS经过了非常广泛/严格?(extensively)的性能测试,这种JSP/类加载器模式并不是性能上的障碍。这种模式对内存的额外开销相对比较小。
Q: 如果我有一个ear文件,里边有war和EJB jars,在改动JSP的时候是否需要重新生成ear?如果是的话,那是否意味着会给webapp和jsp重新创建一个类加载器?
A: 如我这次谈话中说到的,我不推荐在开发过程中打包成EAR。如果你是在开发中部署的目录,只需要编辑好JSP之后在浏览器中点击“reload”。
Q: 目录是否不适合部署在产品模式下?
A: 目录部署只在单机的开发模式下支持。Wlpackage任务可以用来将应用程序打包成标准的EAR。
Q: 关于在WebLogic集群环境下的开发,您还有些其它的建议吗?
A: 通常我建议每一个开发人员都使用他自己的WLS实例。相比共享的环境我更加喜欢这种方式。测试应该在集群环境进行,但是开发人员可以使用单机来进行开发。
Q: 如果Beans是远程的,“co-location”时WLS是否会不做marshalling 和unmarshalling?
A: 使用本地接口的EJB是call-by-reference(如同标准的java 调用)。采用远程接口的EJB默认是call-by-value。
当远程的调用者和被调用者都在同一个WLS实例中时,远程调用会经过一个优化的RMI栈。这过程中不会打开套接字,同时RMI栈会避免在java.lang.String 这样的immutable类型上做 marshalling/unmarshalling。对于Mutable类型,Java序列化会发生。