问题说明:
       1.程序(web)需要实现一个客户端来备份服务器数据库的功能。
       2.数据库是postgresql,备份命令在linux下为:/usr/local/pgsql/bin/pg_dump dbname -U dbuser >要保存的路径文件(如:./aaa.dmp);
       3.现通过Runtime.getRuntime().exec()命令来执行。代码如下:backupCmd = "/usr/local/pgsql/bin/pg_dump books2 -n books_" 
+ sch_id + " -U postgres -c >" + address + "books_" + sch_id + "_" + num + ".dmp";

process = Runtime.getRuntime().exec(backupCmd);

System.out.print(Utils.loadStream(process.getInputStream()));
System.err.print(Utils.loadStream(process.getErrorStream()));Utils.loadStream()的代码:public static String loadStream(InputStream in) throws IOException {

int ptr = 0;
try {
in = new BufferedInputStream(in);
StringBuffer buffer = new StringBuffer();  
while ((ptr = in.read()) != -1) {
    buffer.append((char)ptr);
}

return buffer.toString();
} catch (IOException ioe) {
ioe.printStackTrace();
throw ioe;
}
    }程序无反应。并报出错误如下:
java.lang.NullPointerException
at org.apache.jsp.jsp.error.errorPage_jsp._jspService(errorPage_jsp.java:96)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:94)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:324)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:704)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:476)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:409)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312)
at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:396)
at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:301)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:147)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:118)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929)
at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160)
at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:300)
at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:374)
at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:743)
at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:675)
at org.apache.jk.common.SocketConnection.runIt(ChannelSocket.java:866)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)
at java.lang.Thread.run(Thread.java:534)2009-12-03 13:25:57 org.apache.catalina.core.StandardHostValve@6270b: Exception Processing ErrorPage[errorCode=404, location=/jsp/error/errorPage.jsp]
org.apache.jasper.JasperException
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:372)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:704)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:476)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:409)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312)
at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:396)
at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:301)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:147)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:118)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929)
at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160)
at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:300)
at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:374)
at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:743)
at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:675)
at org.apache.jk.common.SocketConnection.runIt(ChannelSocket.java:866)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)
at java.lang.Thread.run(Thread.java:534)
还请高手指点。

解决方案 »

  1.   

            int ptr = 0;        
            try {
                in = new BufferedInputStream(in);
                StringBuffer buffer = new StringBuffer();  
                while ((ptr = in.read()) != -1) {
                    buffer.append((char)ptr);
                }
                
                return buffer.toString();
            } catch (IOException ioe) {
                ioe.printStackTrace();
                throw ioe;
            }你把上面那段代码中的try...catch语句去掉。然后在jsp中打印异常信息出来试试。
    我觉得可能是上面那段代码抛异常,导致返回了null,然后产生了空指针。
      

  2.   

    check jsp file
    null data is used in jsp file . 
      

  3.   

    errorCode=404, location=/jsp/error/errorPage.jsp
    路径问题吧
      

  4.   

    把你jsp跳转相关的代码贴下看看,找不到你的/jsp/error/errorPage.jsp 
    然后jsp里面引用的参数报空了。
      

  5.   

    报错确实和Utils.loadStream()这个方法无关。错误日志可能是由于我的exec命令错误导致的原因。现在按照问题描述的命令执行,没有那个空指针错误,(ps:空指针错误是由于线程java.lang.Thread.run(Thread.java:534)产生的 )。
    现在关键问题是没有起到备份的作用,要生成的文件没有生成。
    希望有在java中调用linux命令的高手指点一二。还有那个“ >”linux的重定向输出,是不是我要在自己的代码中实现?再次多谢大家的回复。
      

  6.   

    用ssh工具,在里面执行那个命令是没有问题的。
    在网上找到点资料了,好像与重定向有关。
      

  7.   

    process.waitFor();
    加上这个看看,也许是你的命令没执行完就被终止了。
      

  8.   

    process.waitFor()加了,好像主要还是重定向的问题,现在备份基本搞定了。
    接下来主攻还原了。
      

  9.   

                System.out.print(Utils.loadStream(process.getInputStream()));
                System.err.print(Utils.loadStream(process.getErrorStream()));
    是不是因为有这两行代码,命令的输出流被重定向到你的java程序里了呢?
    去掉试试。
      

  10.   

    纯粹 Debug 就能解决的问题。楼主自己搞。
      

  11.   

    public static String loadStream(InputStream in) throws IOException {
            
            int ptr = 0;        
            try {
                in = new BufferedInputStream(in);            StringBuffer buffer = new StringBuffer();  
                while ((ptr = in.read()) != -1) {
                    buffer.append((char)ptr);
                }
                
                return buffer.toString();
            } catch (IOException ioe) {
                ioe.printStackTrace();
                throw ioe;
            }
        }红色的地方有问题。
    in是你方法的入参,你却在方法内部给它赋值然后又修改了。这样毫无用处。空指针就是这里产生的。如果不想用带缓冲读,直接删除红色那一行;如果一定要用带缓冲读可以修改为:
    重新申明一个BufferdInputStream的局部变量
    BufferedInputStream bis = new BufferedInputStream(in);以下用bis代替in进行操作建议你去学习一下C,了解一下函数参数传递方式:值传递与引用传递(java是值传递)。C有指针,所以函数可以改变入参,java没有指针,你想这样修改入参肯定是错的
      

  12.   

    多谢楼上兄弟指点,现在好像已经不是这个原因了。因为现在没用这个方法了。而是参考网上一位大侠的,
    用了public class StreamGobbler extends Thread;
    public void run() {
    try {

    int byteread = 0;
    BufferedOutputStream bufOut = null;
    byte[] buffer = new byte[1024 * 4];;

    BufferedInputStream bufIn = new BufferedInputStream(is);

    if(null != os)  bufOut = new BufferedOutputStream(os);

    while ((byteread = bufIn.read(buffer)) != -1)
    {
    if (null != bufIn) bufOut.write(buffer, 0, byteread);
    System.out.println(buffer);
    }

    if (null != bufOut) bufOut.close();
    bufIn.close();
    } catch (IOException ioe) {
    ioe.printStackTrace();
    }
    }
      

  13.   

    调用改成:StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "ERROR");
    StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), "OUTPUT", fos);

    errorGobbler.start();
    outputGobbler.start();
      

  14.   

    现在就是备份的时候,数据多的时候,文件备份不完全。
    还有就是恢复的时候,不知道要怎么写:StreamGobbler outputGobbler = new StreamGobbler(bufIn, "OUTPUT", process.getOutputStream());


    outputGobbler.start();这样做好像有问题。
      

  15.   


    你现在的解决办法引用了线程,这样处理比较好,效率高,不过要注意同步问题,避免带来数据的不一致
    run方法里面用了os变量,不知是类变量还是实例变量,这里要注意一下。
    在你代码核心部分加一个synchronized块吧
      

  16.   

    服务器的jvm内存已经设置为:JAVA_OPTS="-server -Xmx512m -Xms128m -Djava.awt.headless=true"应该不是内存的问题吧?
      

  17.   

    os变量是类的私有变量,现在代码改为如下:public synchronized void run() {
    try {
    int byteread = 0;
    BufferedOutputStream bufOut = null;
    byte[] buffer = new byte[1024 * 2];;

    BufferedInputStream bufIn = new BufferedInputStream(is);

    if(null != os)  bufOut = new BufferedOutputStream(os);

    while ((byteread = bufIn.read(buffer)) != -1)
    {
    if (null != bufIn) bufOut.write(buffer, 0, byteread);
    System.out.println(buffer);
    }

    if (null != bufOut) {
    bufOut.flush();
    bufOut.close();
    }
    bufIn.close();
    } catch (IOException ioe) {
    ioe.printStackTrace();
    }
    }不过还是有问题啦。
      

  18.   

    在while循环里面进行flush
    可以控制一下当读取了一定字节数后再进行flush
      

  19.   

    try   可以解决~~
      

  20.   

    即时flush也不行,还是备份不完全。
    现在想换一种思路,用java调用shell脚本,不知道是不是效率高点。
    感觉这个还真麻烦。现在本地没有安装数据库,调试起来一点都不方便。
      

  21.   

    你说文件大的时候备份不完全,又看了你的输入输出流是从Runtime获取的,中间所有数据都在你的Runtime中缓存。Runtime能够获取多少内存?还是用java调用系统shell命令,肯定比java直接操作效率高,而且安全。类似你在终端手动输入shell命令一样。
      

  22.   

    正如楼上所说,确实用调用shell脚本搞定。
    空指针后来看了服务器输出,是别的错误导致。
    忙了几天终于有了结果,发现自己对Java的很多东西还真的不熟悉,还的多多加油,谢谢在坐各位xdjm了。
      

  23.   

    首先恭喜楼主解决了问题~~~~
    个人观点:
    毕竟类似Linux,Windows之类的OS都是基于C的实现,而且都预留了对C接口的系统调用库,可以直接嵌入在C代码中调用,但JAVA对OS的系统调用方面就没有这么方便,只能曲线一下,很有限的进行系统调用有一年多没做JAVA了,现在搞VxWorks嵌入式开发,对C和操作系统之间的关系有一定了解。感觉如果要深入了解JAVA,还是抽点时间学学C比较好。主要是把C的指针搞透彻对JAVA学习和理解非常有利