Java,实战,模拟SpringBoot执行jar包启动原理

Java,实战,模拟SpringBoot执行jar包启动原理背景一个应用了多年的自己编写的java的启动方式,觉得甚是方便,大致与SpringBoot启动jar的方式类似,于是就想把它共享出来,共勉之。启

大家好,欢迎来到IT知识分享网。

背景

一个应用了多年的自己编写的java的启动方式,觉得甚是方便,大致与SpringBoot启动jar的方式类似,于是就想把它共享出来,共勉之。

启动时序:

Java,实战,模拟SpringBoot执行jar包启动原理

核心类图:

Java,实战,模拟SpringBoot执行jar包启动原理

代码共享

java核心源码:

package com.what21;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

public class BootstrapClassLoader extends URLClassLoader {

	static final String JAR = ".jar";

	static final String ZIP = ".zip";

	public BootstrapClassLoader(URL[] urls) {
		super(urls);
	}

	public static class Build {

		/**
		 * @param parentPath
		 * @return
		 */
		public static BootstrapClassLoader build(String parentPath) {
			URL[] urls = toURL(parentPath);
			// System.out.println(Arrays.toString(urls));
			return new BootstrapClassLoader(urls);
		}

		/**
		 * @param parentPath
		 * @return
		 */
		public static URL[] toURL(String parentPath) {
			if (parentPath == null) {
				return null;
			}
			File file = new File(parentPath);
			if (!file.exists()) {
				return null;
			}
			List<String> pathList = new ArrayList<String>();
			listFile(parentPath, pathList);
			URL[] urlArray = new URL[pathList.size()];
			for (int i = 0; i < pathList.size(); i++) {
				try {
					urlArray[i] = new URL("file:///" + pathList.get(i));
				} catch (MalformedURLException e) {
					e.printStackTrace();
				}
			}
			return urlArray;
		}

		/**
		 * @param filePath
		 * @param pathList
		 */
		static void listFile(String filePath, List<String> pathList) {
			File file = new File(filePath);
			File[] files = file.listFiles();
			for (File subFile : files) {
				recursionFile(subFile.getAbsolutePath(), pathList);
			}
		}

		/**
		 * @param filePath
		 * @param pathList
		 */
		static void recursionFile(String filePath, List<String> pathList) {
			File file = new File(filePath);
			if (file.isDirectory()) {
				for (File subFile : file.listFiles()) {
					listFile(subFile.getAbsolutePath(), pathList);
				}
			} else {
				String absolutePath = file.getAbsolutePath().toLowerCase();
				if (absolutePath.endsWith(".jar") || absolutePath.endsWith(".zip")) {
					pathList.add(file.getAbsolutePath());
				}
			}
		}

	}

}
package com.what21;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;

public final class Bootstrap {

	private static final String BIN = "bin";
	private static final String LIB = "lib";
	private static final String APPS = "apps";
	private static final String launchClass = "com.what21.apps.ApplicationBootstrap";
	private static final String launchMethod = "launch";
	private static BootstrapClassLoader bootstrapClassLoader;

	/**
	 * @return
	 */
	private static String applicationHome() {
		// 获取当前系统编码
		String encoding = System.getProperty("sun.jnu.encoding");
		if (encoding == null || "".equals(encoding)) {
			encoding = "UTF-8";
		}
		// 获取URL,进行解码
		String runPath = Bootstrap.class.getProtectionDomain().getCodeSource().getLocation().getPath();
		String decodeRunPath = null;
		try {
			decodeRunPath = URLDecoder.decode(runPath, encoding);
		} catch (Exception e) {

		}
		File runFile = new File(decodeRunPath);
		if (!runFile.exists()) {
			try {
				decodeRunPath = URLDecoder.decode(runPath, "UTF-8");
			} catch (Exception e) {

			}
			runFile = new File(decodeRunPath);
		}
		File runHomeFile = runFile.getParentFile();
		String homePath = "";
		if (BIN.equalsIgnoreCase(runHomeFile.getName())) {
			homePath = runHomeFile.getParent();
		} else {
			homePath = runHomeFile.getAbsolutePath();
		}
		return homePath;
	}

	/**
	 * @param obj
	 */
	private static void logger(Object obj) {
		System.out.println(obj);
	}

	/**
	 * @param pidPath
	 * @param pid
	 */
	private static void writeProcessPid(String pidPath, String pid) {
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(new File(pidPath));
			fos.write(pid.getBytes());
			fos.flush();
		} catch (Exception e) {
			System.err.println(e.getMessage());
		} finally {
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				fos = null;
			}
		}
	}

	/**
	 * @param applicationApps
	 * @return
	 */
	private static String[] toApplicationArray(String applicationApps) {
		List<String> appList = new ArrayList<String>();
		File appsFile = new File(applicationApps);
		if (appsFile != null) {
			File[] appFileArray = appsFile.listFiles();
			for (File appFile : appFileArray) {
				if (appFile.isDirectory()) {
					appList.add(appFile.getAbsolutePath());
				}
			}
		}
		return appList.toArray(new String[] {});
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		long startTime = System.currentTimeMillis();
		logger("/////////////////////////////////////////////////////////////////////////////////////////////");
		logger("/////////////////////////////////////////////////////////////////////////////////////////////");
		// logger("// sun.jnu.encoding: " + System.getProperty("sun.jnu.encoding"));
		logger("// file.encoding: " + System.getProperty("file.encoding"));
		// home
		String applicationHome = applicationHome();
		System.setProperty("application.home", applicationHome);
		logger("// application.home: " + applicationHome);
		// lib
		String applicationLib = applicationHome + "/" + LIB + "/";
		System.setProperty("application.lib", applicationLib);
		logger("// application.lib: " + applicationLib);
		// apps
		String applicationApps = applicationHome + "/" + APPS + "/";
		System.setProperty("application.apps", applicationApps);
		logger("// application.apps: " + applicationApps);
		bootstrapClassLoader = BootstrapClassLoader.Build.build(applicationLib);
		logger("// application.classloader: " + bootstrapClassLoader);
		logger("/////////////////////////////////////////////////////////////////////////////////////////////");
		String[] applicationPathArray = toApplicationArray(applicationApps);
		// invoke
		try {
			Class<? extends Object> clazz = bootstrapClassLoader.loadClass(launchClass);
			Object object = clazz.newInstance();
			Method method = clazz.getDeclaredMethod(launchMethod, new Class[] { String[].class });
			method.setAccessible(true);
			method.invoke(object, new Object[] { applicationPathArray });
		} catch (Exception e) {
			e.printStackTrace();
		}
		logger("/////////////////////////////////////////////////////////////////////////////////////////////");
		String runName = ManagementFactory.getRuntimeMXBean().getName();
		logger("// application.name: " + runName);
		if (runName != null) {
			String pid = runName.split("@")[0];
			writeProcessPid(applicationHome + "/" + BIN + "/process.pid", pid);
		}
		long endTime = System.currentTimeMillis();
		logger("// Application startup in " + (endTime - startTime) + " ms");
		logger("/////////////////////////////////////////////////////////////////////////////////////////////");
		logger("/////////////////////////////////////////////////////////////////////////////////////////////");
	}

}

Linux启动脚本:

#!/bin/bash

#==========================================================================================
# export JAVA_HOME=/opt/java/jdk1.8.0_221
export PATH=$JAVA_HOME/bin:$PATH
export JAVA_OPTS="-Xmx1024M -Xms512M -XX:MaxPermSize=256m"
export JAVA_JAR="startup-single-2.0.jar"
export JAVA_MAIN="com.what21.startup.SingleStartUp"
export LAUNCH_CLASS="com.what21.simba.netserv.launch.NetServDaemon.launch"
export LAUNCH_ARGS=""
export WORK_HOME=$(dirname "$PWD")
#==========================================================================================
export CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:$CLASSPATH
#==========================================================================================
echo "Java Home <=====> $JAVA_HOME"
echo "JVM Parameters <=====> $JAVA_OPTS"
echo "Start Jar <=====> $JAVA_JAR"
echo "Start Class <=====> $JAVA_MAIN"
echo "Launch Class <=====> $LAUNCH_CLASS"
echo "Start Parameters <=====> $LAUNCH_ARGS"
echo "Execute Command <=====> $CMD"
#==========================================================================================
nohup $JAVA_HOME/bin/java -DWorkHome=$WORK_HOME $JAVA_OPTS -classpath "$CLASSPATH:./$JAVA_JAR" "$JAVA_MAIN" "$LAUNCH_CLASS" "$LAUNCH_ARGS" "$CMD" >/dev/null 2>&1 &
#==========================================================================================

Windows启动脚本:

@echo off

rem ========================================================================
rem set JAVA_HOME=D:\MyApps\Java\jdk1.8.0_131
set JAVA_OPTS="-Xmx1024M -Xms512M -XX:MaxPermSize=256m"
set JAVA_JAR="startup-single-2.0.jar"
set JAVA_MAIN="com.what21.startup.SingleStartUp"
set LAUNCH_CLASS="com.what21.simba.netserv.launch.NetServDaemon.launch"
set LAUNCH_ARGS=
rem ========================================================================
set CLASSPATH=.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar
set WORK_HOME=%cd%
rem ========================================================================
rem 接收传入参数 
rem ========================================================================

if "%1"=="" goto doStart
if "%1"=="start" goto doStart
if "%1"=="stop" goto doShutdown

rem ========================================================================

:doStart
set CMD=start
goto doExe

rem ========================================================================

:doShutdown
set CMD=stop
goto doExe

rem ========================================================================

:doExe
echo "================================================================================================================"
echo "Execute Directory <=====> %WORK_HOME%"
echo "Java Home <=====> %JAVA_HOME%"
echo "JVM Parameters <=====> %JAVA_OPTS%"
echo "Start Jar <=====> %JAVA_JAR%"
echo "Start Class <=====> %JAVA_MAIN%"
echo "Launch Class <=====> %LAUNCH_CLASS%"
echo "Start Parameters <=====> %LAUNCH_ARGS%"
echo "Execute Command <=====> %CMD%"
echo "================================================================================================================"

echo.
%JAVA_HOME%\bin\java -DWorkHome=$WORK_HOME "%JAVA_OPTS%" -classpath "%CLASSPATH%;%JAVA_JAR%" "%JAVA_MAIN%" "%LAUNCH_CLASS%" "%LAUNCH_ARGS%" "%CMD%" &
pause
goto end 

rem ========================================================================

:notParam
echo not params

rem ========================================================================

:end

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/66633.html

(0)
上一篇 2024-05-27 14:00
下一篇 2024-05-31 10:45

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信