October 10
JPDA是一个多层的调试框架,包括 JVMDI、JDWP、JDI 三个层次。JAVA 虚拟机提供了JPDA的实现。其开发工具作为调试客户端,可以方便的与虚拟机通讯,进行调试
- JVMDI定义了虚拟机需要实现的本地接口
- JDWP 定义了JVM与调试客户端之间的通讯协议
- JDI 则是一组JAVA接口
如果是一个 JAVA 的调试客户端,只要实现 JDI 接口,利用JDWP协议,与虚拟机通讯,就可以调用JVMDI了
JSR-45规范
JSR-45(Debugging Support for Other Languages)为那些非 JAVA 语言写成,却需要编译成 JAVA 代码,运行在 JVM 中的程序,提供了一个进行调试的标准机制。也许字面的意思有点不好理解,什么算是非 JAVA 语言呢?其实 JSP 就是一个再好不过的例子,JSR-45 的样例就是一个 JSP。
JSP的调试一直依赖于具体应用服务器的实现,没有一个统一的模式,JSR-45 针对这种情况,提供了一个标准的模式。我们知道,JAVA 的调试中,主要根据行号作为标志,进行定位。但是 JSP 被编译为 JAVA 代码之后,JAVA 行号与 JSP 行号无法一一对应,怎样解决呢?
JSR-45 是这样规定的:JSP 被编译成 JAVA 代码时,同时生成一份 JSP 文件名和行号与 JAVA 行号之间的对应表(SMAP)。JVM 在接受到调试客户端请求后,可以根据这个对应表(SMAP),从 JSP 的行号转换到 JAVA 代码的行号;JVM 发出事件通知前, 也根据对应表(SMAP)进行转化,直接将 JSP 的文件名和行号通知调试客户端。
参考:http://www-128.ibm.com/developerworks/cn/opensource/os-jspdebug/
现在大部分的IDE环境都有远程调试功能,如JBuilder,Eclipse,IDEA等等
步骤:
1、修改服务器JVM参数,添加对JPDA支持,启动Java虚拟机时绑定远程调试功能监视端口
以JRun为例,jrun使用JDPA稍显麻烦,因为所有的服务都共享同样JVM参数,第二个服务启动后会报端口已被使用的错误
启动JRun前,修改jrun/bin下jvm.config,修改JVM参数
java.args=-Xmx128M -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=2005
监听端口2005
启动JRun后,恢复jvm.config文件JVM参数
2、找到IDE环境远程调试选项,添上服务器主机地址和JPDA监听端口2005
3、在需要调试的程序中添加调试断点,测试IDE就会通知服务器的JVM,某个程序某一行有断点
4、运行程序,调试开始
需要注意的是,被调试的程序编译时必须使用-g,使得编译后的class文件包含调试信息
但是由于JRun并不完全符合JSR-45规范,所以还没有找到jsp的调试方法,但是对于Tomcat5或Resin3.0都可以进行jsp断点调试
July 22
web上经常有这样的需求,一个select B内容是根据另一个select A对应的值查询而来的。每次A 选的值变化的话,都需要重新查询数据库。但是要求不能刷新页面。实现
显示页面
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=gb2312">
</HEAD>
<BODY>
虚拟社区核心数据webservice<br>
<SELECT NAME="sel" id="sel" onChange="getNewText.src='test.js'">
<option value=1>1</option>
<option value=2>2</option>
<option value=3>3</option>
<option value=4>4</option>
</SELECT>
<span id="span">123213</span>
<script id="getNewText"></script>
</BODY>
</HTML>
test.js代码(不一定非得是js,可以是jsp,asp都一样,但内容必须是javascript)
document.getElementById("span").innerHTML="<select><option>aaaa</option><option>234234</option></select>";
原理就是定义一个javascript脚本对象,但其内容都是每次到服务器上取得。
完美解决!
July 07
在网上看了很多关于ChartDirector中文问题的解决办法,那我也说一个吧
在windows上只要设置一下字体就可以了
Chart.setDefaultFonts("Simsun","Simsun","Simsun"),三个参数分别是默认字,粗体字和斜体字的字体
在Linux上同样也要设置字体,并且设置Linux默认字符集为GB18030,否则可能有乱码问题哦(没试过,如果有乱码就需要转码了)。
还有个很重要的地方就是设置服务器的启动参数(这一点绝对是原创)-Djava.awt.headless=true
根据Sun网站上的意思是因为linux服务器大部分是字符型界面,不需要UI的支持,这时的java虚拟机省略了UI的功能,所以生成图片时调用打印文字的api会有问题。加上这个参数就OK了。
June 25
在网上发现两个很好的图形报表工具,有兴趣的可以研究一下阔,说不定什么时候会用到哦。
JFreeChart:开源免费,效果一般般,重要优点--免费
ChartDirecto:非常棒的东东,做出的图形很漂亮。不过需要$。
可能有些人会破解,哎,人家辛辛苦苦做出的东西,又不是很富有。破解它,忍心吗?这种人有点龌龊哦。我就不会做这样的事
我会用破解好的,哈哈哈哈。。。。(周星星的笑声响起)
June 24
呵呵,网上好多对动态处理介绍时的异常处理都有问题。关键是拦截类在调用实际接口实现类时的处理:
try{
return method.invoke(target,args);
}catch(InvocationTargetException e){
if(e.getTargetException() != null)
throw e.getTargetException();
else
throw e;
}
找到实际的异常,并抛出。
谢谢帮忙的邵琪妹妹
。
java动态代理机制对于实现AOP编程思想是个非常好的技术手段,但性能上可能有一定影响,会比普通的直接调用速度降低一倍。如果性能上要求非常严的话,可以像JDO一样使用欲编译,改变字节码。呵呵,这不是今天要讨论的问题。
在测试动态代理机制是发现一个严重的问题,不知道大家是怎么解决的,还是我写的代码是错的。
拦截类:
public class LogHandle implements InvocationHandler {
private Object target; //被拦截的对象
public LogHandle(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(target,args);
System.out.println("-- invocation Handler end");
return result;
}
}
接口定义:
public interface ITest {
public void setName(String name)throws TestException ;
}
接口实现:
public class TestImpl implements ITest{
private String name;
public void setName(String name)throws TestException {
this.name = name;
System.out.println("setName()");
//如果name为null,则抛出TestException异常
if(name == null)throw new TestException("name can't be null");
}
}
拦截代码:
public static ITest getTest(){
TestImpl testImpl = new TestImpl();
LogHandle handle = new LogHandle(testImpl);
ITest test = null;
test = (ITest) Proxy.newProxyInstance(testImpl.getClass().getClassLoader(),
TestImpl.class.getInterfaces(),
handle);
return test;
}
public void test(){
try{
getTest().setName(null);
}catch(TestException e){
System.out.println("TestException = " + e.getMessage());
e.printStackTrace();
}
}
从代码上看没问题,关键是红字的部分,运行时捕获不到TestException,因为抛出的是
java.lang.reflect.UndeclaredThrowableException
如果用工厂类返回专门产生ITest接口时,调用代码在处理时就会不知所措。因为它不知道返回的ITest接口是动态代理产生的的,还是TestImpl 返回的接口。运行时捕获不到TestException,程序肯定会出问题。
不知道实际运用动态代理时,是如何处理此问题的。
struts已经用了很长时间了,感觉没什么新意了,老生常谈。现在网上关于webwork2的介绍比较多,想有空研究一下。
May 30
实际上使用axis进行webservice开发是件非常容易的事,主要的工作是就是配置xml和写生成帮助类的ant脚本。
web.xml
<servlet>
<servlet-name>AxisServlet</servlet-name>
<display-name>Apache-Axis Servlet</display-name>
<servlet-class>
org.apache.axis.transport.http.AxisServlet
</servlet-class>
</servlet>
<servlet>
<servlet-name>AdminServlet</servlet-name>
<display-name>Axis Admin Servlet</display-name>
<servlet-class>
org.apache.axis.transport.http.AdminServlet
</servlet-class>
<load-on-startup>100</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>/servlet/AxisServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
其中AxisServlet的作用是解析客户端发来的SOAP包,调用服务,并返回SOAP封装的结果。
而AdminServlet的作用就是使用ant脚本部署,在服务器端生成server-config.wsdd(里面包含提供的webservice服务),如果熟悉wsdd(webservice部署描述符)文件,可以手动更改次文件也一样。
ant脚本
<target name="java2wsdl">
<axis-java2wsdl
classname="com.newpalm.vcommunity.webservice.${package}.I${serviceName}"
location="${WEB_URL}/services/${serviceName}"
namespace="urn:${package}.vcommunity"
output="${serviceName}.wsdl"
style="RPC"
>
</axis-java2wsdl>
</target>
<target name="wsdl2java">
<axis-wsdl2java all="true"
url="${serviceName}.wsdl"
deployscope="Request"
serverside="true"
skeletondeploy="false"
testcase="true"
noimports="false"
typemappingversion="1.2">
<mapping namespace="urn:${package}.vcommunity" package="com.newpalm.vcommunity.webservice.${package}"/>
</axis-wsdl2java>
</target>
<target name="deploy">
<axis-admin
port="${port}"
hostname="${host}"
failonerror="true"
servletpath="/${contextName}/services/AdminService"
debug="true"
xmlfile="${src.dir}/com/newpalm/vcommunity/webservice/${package}/deploy.wsdd"
/>
</target>
其中java2wsdl的作用是根据服务接口生成wsdl文件,wsdl2java的作用是根据wsdl文件生成客户端、服务器端帮助类,服务实现类,还有deploy/undeploy文件。
需要注意的是webservice接口不要使用java独有的对象,如map或list,尽量使用POJO对象或原始类型。否则。。。。。。