java使用java -jar在当前应用程序调度另一可执行程序

最近,在研究公司的调度平台,也就是在某一应用程序中调用另一个应该程序,从而完成相应的业务逻辑。这里,另一应用程序是以jar包的方式提供。
下面,笔者直接贴代码,相关的解释已于注释:

/**
 * Project Name:testJava
 * File Name:JarInvoke.java
 * Package Name:com.qiyongkang.javaJar
 * Date:2015年9月18日上午9:02:58
 * Copyright (c) 2015, CANNIKIN(http://http://code.taobao.org/p/cannikin/src/) All Rights Reserved.
 *
 */

package com.qiyongkang.javaJar;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * ClassName:JarInvoke <br/>
 * Function: TODO ADD FUNCTION. <br/>
 * Reason: TODO ADD REASON. <br/>
 * Date: 2015年9月18日 上午9:02:58 <br/>
 *
 * @author qiyongkang
 * @version
 * @since JDK 1.6
 * @see
 */
public class JarInvoke {

    /*
     * 本示例是使用的java -jar方式调度程序
     * 触发调用一个应用程序,1:以jar的方式运行 2:通过当前线程的contextClassLoader来加载外部jar,然后通过反射调用main方法
     * jar方式表示的进程级调用,另外一种方式表示内部加载类,以线程的方式去运行
     * 调用运行jar的JVM参数,如果选择以线程的方式去运行,那么这个参数将不起作用
     *
     * 2.类加载方式,然后通过反射
     * 每个运行中的线程都有一个成员contextClassLoader,用来在运行时动态地载入其它类
     * 系统默认的contextClassLoader是systemClassLoader,
     * 所以一般而言java程序在执行时可以使用JVM自带的类、$JAVA_HOME/jre/lib/ext/中的类和$CLASSPATH/中的类,
     * 对于非默认的jar,一般只能手动在配置环境添加。
     * 但事实上,我们可以通过Thread.currentThread().setContextClassLoader()更改当前线程的contextClassLoader行为,
     * 实现在程序内加载外部jar
     * ClassLoader的工作原理是:
     *  1) 线程需要用到某个类时,contextClassLoader将被请求来载入该类
     *  2) contextClassLoader请求它的父ClassLoader来完成该载入请求
     *  3) 如果父ClassLoader无法载入类,则contextClassLoader试图自己来载入
     *  这种方式,在没有优化的前提下,这种直接加载外部包的速度在jvm会有很大损耗,所以并不适合直接运用在需要复杂运算的jar中类调用上
     */
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("java ");
        // 添加JVM参数
        sb.append("-Xms128m -Xmx256m -Xss1m ");

        // 所执行的jar路径名
        sb.append("-jar ");
        sb.append("./ShutDown/com.qiyongkang.shutdown.ShutDown.1.0.0.jar ");

        // 添加应用程序运行时传递的参数
        sb.append("3600");

        String cmd = sb.toString();

        try {
            Process process = Runtime.getRuntime().exec(cmd);
            // 读取子进程中的输入流信息,必须读取流信息,否则进程运行一段时间后会被挂起而不运行!
            // 先读取错误流,在读取标准流
            JarInvoke jarInvoke = new JarInvoke();
            jarInvoke.new ProcessStreamHelper(process.getErrorStream(), ProcessStreamHelper.ERROR_STREAM).start();
            jarInvoke.new ProcessStreamHelper(process.getInputStream(), ProcessStreamHelper.NORMAL_STREAM).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * ClassName: ProcessStreamHelper <br/>
     * 子进程流读取帮助类,用来读取进程中的流信息.
     * <p/>
     *
     * @author qiyongkang
     * @since JDK 1.6
     */
    class ProcessStreamHelper extends Thread {

        final static int NORMAL_STREAM = 0;

        final static int ERROR_STREAM = 1;

        private InputStream is;

        private int streamType;

        ProcessStreamHelper(InputStream is, int streamType) {
            super();
            this.is = is;
            this.streamType = streamType;
        }

        @Override
        public void run() {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            String line = null;
            try {
                while ((line = reader.readLine()) != null) {
                    line = new String(line.getBytes(), "UTF-8");
                    if (streamType == NORMAL_STREAM) {
                        // debugLog("Read Line: " + line);
                    } else if (streamType == ERROR_STREAM) {
                        errorLog("Read Error: " + line);
                    } else {
                        // debugLog("Unkown Input Stream Type[" + streamType +
                        // "]");
                    }
                }
            } catch (IOException e) {
                errorLog("IOE: " + e + "\t\tMessage: " + e.getMessage());
            }
        }

        void debugLog(String message) {
            System.out.println("[Invoker Debug] " + message);
        }

        void errorLog(String message) {
            System.err.println("[Invoker Error] " + message);
        }
    }
}

我的项目结构展示如下图:
这里写图片描述
这里我的jar包使用ant打的包,相关的Main-Class和ClassPath已在MANIFEST.MF中指定:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.4
Created-By: 1.7.0_79-b15 (Oracle Corporation)
Main-Class: com.qiyongkang.shutdown.ShutDown
Class-Path: lib/commons-logging-1.1.3.jar lib/druid-1.0.0.jar

就写到这里了,有点偷懒,但也说得很清楚,这种调度程序的场景在某些项目中会使用到,比如数据处理,需要定期执行,因此便可打成jar包,放在统一的调度平台来调度执行这些jar程序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值