public static synchronized void main(String[] args) {

		if (serverSocketFactory != null) {
			throw new IllegalStateException("Server previously started within JVM");
		}

		if (args.length == 0) {
			displayHelp();
			System.exit(-1);
		}

		if (server != null) {
			throw new AssertException("Server already started");
		}

		int basePort = DEFAULT_PORT;
		AuthMode authMode = NO_AUTH_LOGIN;
		boolean nameCallbackAllowed = false;
		boolean altSSHLoginAllowed = false;
		boolean allowAnonymousAccess = false;
		String loginDomain = null;
		String rootPath = null;
		int defaultPasswordExpiration = -1;
		boolean autoProvision = false;
		File jaasConfigFile = null;

		// Network name resolution disabled by default
		InetNameLookup.setLookupEnabled(false);

		// Initialize application
		try {
			ApplicationLayout layout = new GhidraServerApplicationLayout();
			ApplicationConfiguration configuration = new ApplicationConfiguration();
			configuration.setInitializeLogging(false);
			Application.initializeApplication(layout, configuration);
		}
		catch (IOException e) {
			System.err.println("Failed to initialize the application!");
			System.exit(-1);
		}

		// Process command line options
		for (int i = 0; i < args.length; i++) {
			String s = args[i];
			if (s.startsWith("-p")) { // RMI Registry Server Port option
				try {
					basePort = Integer.parseInt(s.substring(2));
				}
				catch (NumberFormatException e1) {
					basePort = -1;
				}
				if (basePort <= 0 || basePort > 65535) {
					displayUsage("Invalid registry port specified");
					System.exit(-1);
				}
			}
			else if (s.startsWith("-a") && s.length() == 3) { // Authentication Mode
				int authModeNum = Integer.MIN_VALUE;
				try {
					authModeNum = Integer.parseInt(s.substring(2));
				}
				catch (NumberFormatException e1) {
					displayUsage("Invalid option: " + s);
					System.exit(-1);
				}

				authMode = AuthMode.fromIndex(authModeNum);

				if (authMode == null) {
					displayUsage("Invalid authentication mode: " + s);
					System.exit(-1);
				}
			}
			else if (s.startsWith("-ip")) { // setting server remote access hostname
				int nextArgIndex = i + 1;
				String hostname;
				if (s.length() == 3 && nextArgIndex < args.length) {
					hostname = args[++i];
				}
				else {
					hostname = s.substring(3);
				}
				hostname = hostname.trim();
				if (hostname.length() == 0 || hostname.startsWith("-")) {
					displayUsage("Missing -ip hostname");
					System.exit(-1);
				}
				System.setProperty(RMI_SERVER_PROPERTY, hostname);
			}
			else if (s.startsWith("-i")) {  // setting server bind address
				int nextArgIndex = i + 1;
				String bindIp;
				if (s.length() == 2 && nextArgIndex < args.length) {
					bindIp = args[++i];
				}
				else {
					bindIp = s.substring(2);
				}
				bindIp = bindIp.trim();
				if (bindIp.length() == 0 || bindIp.startsWith("-")) {
					displayUsage("Missing -i interface bind address");
					System.exit(-1);
				}
				try {
					bindAddress = InetAddress.getByName(bindIp);
				}
				catch (UnknownHostException e) {
					System.err.println("Unknown server interface bind address: " + bindIp);
					System.exit(-1);
				}
			}
			else if (s.startsWith("-d") && s.length() > 2) { // Login Domain
				loginDomain = s.substring(2);
			}
			else if (s.equals("-u")) {
				nameCallbackAllowed = true;
			}
			else if (s.equals("-n")) {
				InetNameLookup.setLookupEnabled(true);
			}
			else if (s.equals("-anonymous")) {
				allowAnonymousAccess = true;
			}
			else if (s.equals("-ssh")) {
				altSSHLoginAllowed = true;
			}
			else if (s.startsWith("-e")) { // default password expiration (days)
				try {
					defaultPasswordExpiration = Integer.parseInt(s.substring(2));
				}
				catch (NumberFormatException e1) {
					// handled by validation below
				}
				if (defaultPasswordExpiration < 0) {
					displayUsage("Invalid default password expiration");
					System.exit(-1);
				}
				else if (defaultPasswordExpiration == 0) {
					System.out.println("Default password expiration has been disbaled.");
				}
			}
			else if (s.startsWith("-jaas")) {
				String jaasConfigFileStr;
				if (s.length() == 5) {
					i++;
					jaasConfigFileStr = (i < args.length) ? args[i] : "";
				}
				else {
					jaasConfigFileStr = s.substring(5);
				}
				jaasConfigFileStr = jaasConfigFileStr.trim();
				if (jaasConfigFileStr.isEmpty()) {
					displayUsage("Missing -jaas config file path argument");
					System.exit(-1);
				}
				jaasConfigFile = getServerCfgFile(jaasConfigFileStr);
				if (!jaasConfigFile.isFile()) {
					displayUsage(
						"JAAS config file (-jaas <configfile>) does not exist or is not file: " +
							jaasConfigFile.getAbsolutePath());
					System.exit(-1);
				}
			}
			else if (s.equals("-autoProvision")) {
				autoProvision = true;
			}
			else {
				if (i < (args.length - 1)) {
					displayUsage("Invalid usage!");
					System.exit(-1);
				}
				rootPath = s;
			}
		}

		if (rootPath == null) {
			displayUsage("Repository directory must be specified!");
			System.exit(-1);
		}

		File serverRoot = new File(rootPath);
		if (!serverRoot.isAbsolute()) {
			ResourceFile installRoot = Application.getInstallationDirectory();
			if (installRoot == null || installRoot.getFile(false) == null) {
				System.err.println("Failed to resolve installation root directory!");
				System.exit(-1);
			}
			serverRoot = new File(installRoot.getFile(false), rootPath);
		}

		if (authMode == JAAS_LOGIN) {
			if (jaasConfigFile == null) {
				displayUsage("JAAS config file argument (-jaas <configfile>) not specified");
				System.exit(-1);
			}
		}

		try {
			serverRoot = serverRoot.getCanonicalFile();
		}
		catch (IOException e1) {
			System.err.println(
				"Failed to resolve repository directory: " + serverRoot.getAbsolutePath());
			System.exit(-1);
		}

		if (!serverRoot.exists() && !serverRoot.mkdirs()) {
			System.err.println(
				"Failed to create repository directory: " + serverRoot.getAbsolutePath());
			System.exit(-1);
		}

		File serverLogFile = new File(serverRoot, "server.log");
		Application.initializeLogging(serverLogFile, serverLogFile);

		// In the absence of module initialization - we must invoke directly
		SSLContextInitializer.initialize();

		log = LogManager.getLogger(GhidraServer.class); // init log *after* initializing log system

		ServerPortFactory.setBasePort(basePort);

		Runtime.getRuntime().addShutdownHook(new Thread((Runnable) () -> {
			if (server != null) {
				server.dispose();
			}
		}, "Ghidra Server Disposer"));

		// Create and install a security manager
		// if (System.getSecurityManager() == null) {
		// 		System.setSecurityManager(new RMISecurityManager());
		// }

		try {
			// Ensure that remote access hostname is properly set for RMI registration
			String hostname = initRemoteAccessHostname();

			if (ApplicationKeyManagerFactory.getPreferredKeyStore() == null) {
				// keystore has not been identified - use self-signed certificate
				ApplicationKeyManagerFactory
						.setDefaultIdentity(new X500Principal("CN=GhidraServer"));
				ApplicationKeyManagerFactory.addSubjectAlternativeName(hostname);
			}
			if (!ApplicationKeyManagerFactory.initialize()) {
				log.fatal("Failed to initialize PKI/SSL keystore");
				System.exit(0);
				return;
			}

			// RMIClassServer.startServer(classSvrPort);

			// String codeBaseProp = "http://" +
			// localhost.getCanonicalHostName() + ":" + classSvrPort + "/";
			// System.setProperty(RMI_CODEBASE_PROPERTY, codeBaseProp);

			log.info("Ghidra Server " + Application.getApplicationVersion());
			log.info("   Server remote access address: " + hostname);
			if (bindAddress == null) {
				log.info("   Server listening on all interfaces");
			}
			else {
				log.info("   Server listening on interface: " + bindAddress.getHostAddress());
			}
			log.info("   RMI Registry port: " + ServerPortFactory.getRMIRegistryPort());
			log.info("   RMI SSL port: " + ServerPortFactory.getRMISSLPort());
			log.info("   Block Stream port: " + ServerPortFactory.getStreamPort());
			log.info("   Block Stream compression: " +
				(RemoteBlockStreamHandle.enableCompressedSerializationOutput ? "enabled"
						: "disabled"));
//			log.info("   Class server port: " + ??);
			log.info("   Root: " + rootPath);
			log.info("   Auth: " + authMode.getDescription());
			if (authMode == PASSWORD_FILE_LOGIN && defaultPasswordExpiration >= 0) {
				log.info("   Default password expiration: " +
					(defaultPasswordExpiration == 0 ? "disabled"
							: (defaultPasswordExpiration + " days")));
			}
			if (authMode != PKI_LOGIN) {
				log.info("   Prompt for user ID: " + (nameCallbackAllowed ? "yes" : "no"));
			}
			if (altSSHLoginAllowed) {
				log.info("   SSH authentication option enabled");
			}
			log.info(
				"   Anonymous server access: " + (allowAnonymousAccess ? "enabled" : "disabled"));

			String enabledCiphers = System.getProperty(TLS_ENABLED_CIPHERS_PROPERTY);
			if (enabledCiphers != null) {
				String[] cipherList = enabledCiphers.split(",");
				log.info("   Enabled cipher suites:");
				for (String s : cipherList) {
					log.info("       " + s);
				}
			}

			serverSocketFactory = new SslRMIServerSocketFactory(null, getEnabledTlsProtocols(),
				authMode == PKI_LOGIN) {
				@Override
				public ServerSocket createServerSocket(int port) throws IOException {
					return new GhidraSSLServerSocket(port, bindAddress, getEnabledCipherSuites(),
						getEnabledProtocols(), getNeedClientAuth());
				}

			};
			clientSocketFactory = new SslRMIClientSocketFactory();

			log.info(SystemUtilities.getUserName() + " starting Ghidra Server...");

			GhidraServer svr = new GhidraServer(serverRoot, authMode, loginDomain,
				nameCallbackAllowed, altSSHLoginAllowed, defaultPasswordExpiration,
				allowAnonymousAccess, autoProvision, jaasConfigFile);

			log.info("Registering Ghidra Server...");

			Registry registry = LocateRegistry.createRegistry(
				ServerPortFactory.getRMIRegistryPort(), clientSocketFactory, serverSocketFactory);
			registry.bind(BIND_NAME, svr);

			log.info("Registered Ghidra Server.");

		}
		catch (IOException e) {
			e.printStackTrace();
			log.error(e.getMessage());
			System.exit(-1);
		}
		catch (Throwable t) {
			log.fatal("Server error: " + t.getMessage(), t);
			System.exit(-1);
		}
	}
Main method for starting the Ghidra server.

@param args  command line arguments
Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/GhidraServer.java