if NOT DEFINED RED5_MAINCLASS set RED5_MAINCLASS=org.red5.server.Bootstrap :launchRed5 echo Starting Red5 "%JAVA_HOME%\bin\java" %JYTHON_OPTS% %JAVA_OPTS% -cp "%RED5_CLASSPATH%" %RED5_MAINCLASS% %RED5_OPTS%
/** * BootStrapping entry point * * @param args command line arguments * @throws Exception if error occurs */ public static void main(String[] args) throws Exception { //retrieve path elements from system properties String root = getRed5Root(); getConfigurationRoot(root); //bootstrap dependencies and start red5 bootStrap(); System.out.println("Bootstrap complete"); }
/** * Gets the Red5 root * * @return * @throws IOException */ private static String getRed5Root() throws IOException { // look for red5 root first as a system property String root = System.getProperty("red5.root"); // if root is null check environmental if (root == null) { //check for env variable root = System.getenv("RED5_HOME"); } // if root is null find out current directory and use it as root if (root == null || ".".equals(root)) { root = System.getProperty("user.dir"); //System.out.printf("Current directory: %s\n", root); } //if were on a windows based os flip the slashes if (File.separatorChar != '/') { root = root.replaceAll("\\\\", "/"); } //drop last slash if exists if (root.charAt(root.length()-1) == '/') { root = root.substring(0, root.length() - 1); } //set/reset property System.setProperty("red5.root", root); System.out.printf("Red5 root: %s\n", root); return root; }
/** * Gets the configuration root * * @param root * @return */ private static String getConfigurationRoot(String root) { // look for config dir String conf = System.getProperty("red5.config_root"); // if root is not null and conf is null then default it if (root != null && conf == null) { conf = root + "/conf"; } //flip slashes only if windows based os if (File.separatorChar != '/') { conf = conf.replaceAll("\\\\", "/"); } //set conf sysprop System.setProperty("red5.config_root", conf); System.out.printf("Configuation root: %s\n", conf); return conf; }
最后来看 bootStrap 句,这个调用的是 bootstrap 方法。这个方法的前半部分写的是启动前的一些属性设置,注释的很详细,不再赘述。直接从后半部分看起,后半部分源码如下:
//get current loader ClassLoader baseLoader = Thread.currentThread().getContextClassLoader(); // build a ClassLoader ClassLoader loader = ClassLoaderBuilder.build(); //set new loader as the loader for this thread Thread.currentThread().setContextClassLoader(loader); // create a new instance of this class using new classloader Object boot = Class.forName("org.red5.server.Launcher", true, loader).newInstance(); Method m1 = boot.getClass().getMethod("launch", (Class[]) null); m1.invoke(boot, (Object[]) null); //not that it matters, but set it back to the original loader Thread.currentThread().setContextClassLoader(baseLoader);这段代码的意思是,先把当前线程的 ClassLoader 置换成 ClassLoaderBuilder 自定义的 ClassLoader,后者的主要作用是将 Red5 依赖的第三方类库加载。之后使用反射机制动态调用 org.red5.server.Launcher.launch 方法。最后将当前线程的 ClassLoader 还原为置换前的 ClassLoader。就这些。