zhengl's profile淡定而从容PhotosBlogLists Tools Help

Blog


    October 10

    具有远程调试的JAVA调试框架(JPDA)简介

    JPDA是一个多层的调试框架,包括 JVMDIJDWPJDI 三个层次。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环境都有远程调试功能,如JBuilderEclipseIDEA等等

    步骤:

    1、修改服务器JVM参数,添加对JPDA支持,启动Java虚拟机时绑定远程调试功能监视端口

       JRun为例,jrun使用JDPA稍显麻烦,因为所有的服务都共享同样JVM参数,第二个服务启动后会报端口已被使用的错误

       启动JRun前,修改jrun/binjvm.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的调试方法,但是对于Tomcat5Resin3.0都可以进行jsp断点调试

    July 22

    javascript动态改变相关select内容选项,不刷新页面

    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

    linux下ChartDirector中文字不显示或乱码问题的解决

    在网上看了很多关于ChartDirector中文问题的解决办法,那我也说一个吧
    在windows上只要设置一下字体就可以了
       Chart.setDefaultFonts("Simsun","Simsun","Simsun"),三个参数分别是默认字,粗体字和斜体字的字体
    在Linux上同样也要设置字体,并且设置Linux默认字符集为GB18030,否则可能有乱码问题哦(没试过,如果有乱码就需要转码了)。
    还有个很重要的地方就是设置服务器的启动参数(这一点绝对是原创)-Djava.awt.headless=true
    根据Sun网站上的意思是因为linux服务器大部分是字符型界面,不需要UI的支持,这时的java虚拟机省略了UI的功能,所以生成图片时调用打印文字的api会有问题。加上这个参数就OK了。
    June 25

    推荐Java图形报表工具

    在网上发现两个很好的图形报表工具,有兴趣的可以研究一下阔,说不定什么时候会用到哦。

    JFreeChart:开源免费,效果一般般,重要优点--免费

    ChartDirecto:非常棒的东东,做出的图形很漂亮。不过需要$。
      可能有些人会破解,哎,人家辛辛苦苦做出的东西,又不是很富有。破解它,忍心吗?这种人有点龌龊哦。我就不会做这样的事

    我会用破解好的,哈哈哈哈。。。。(周星星的笑声响起)

    June 24

    java动态代理对于Exception的处理,OK

    呵呵,网上好多对动态处理介绍时的异常处理都有问题。关键是拦截类在调用实际接口实现类时的处理:
    try{
                return method.invoke(target,args);
            }catch(InvocationTargetException e){
                if(e.getTargetException() != null)
                    throw e.getTargetException();
                else
                    throw e;
            }
    找到实际的异常,并抛出。
    谢谢帮忙的邵琪妹妹

    java动态代理对于Exception的处理,不明白

    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,程序肯定会出问题。

    不知道实际运用动态代理时,是如何处理此问题的。

    学习webwork2

    struts已经用了很长时间了,感觉没什么新意了,老生常谈。现在网上关于webwork2的介绍比较多,想有空研究一下。

    May 30

    使用Axis进行webservice编程

    实际上使用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对象或原始类型。否则。。。。。。