All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.xphsc.util.JVMUtil Maven / Gradle / Ivy

There is a newer version: 1.2.3
Show newest version
package com.github.xphsc.util;

import com.github.xphsc.exception.ExceptionUtil;
import com.github.xphsc.io.StreamUtil;


import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

/**
 * 有关 JVM 处理的工具类。
 * Created by ${huipei.x} on 2017-5-31.
 */
public class JVMUtil {

    private static final String[] MANIFESTS = { "Manifest.mf", "manifest.mf", "MANIFEST.MF" };

    private static final JavaRuntimeInfo JAVA_RUNTIME_INFO = new JavaRuntimeInfo();

    public static boolean appendToClassPath(String name) {
        if (!FileUtil.exist(name)) {
            return false;
        }
        try {
            ClassLoader clsLoader = ClassLoader.getSystemClassLoader();
            Method appendToClassPathMethod =
                    clsLoader.getClass().getDeclaredMethod("appendToClassPathForInstrumentation", String.class);

            if (null != appendToClassPathMethod) {
                appendToClassPathMethod.setAccessible(true);
                appendToClassPathMethod.invoke(clsLoader, name);
            }

            return true;
        } catch (Exception e) {
            throw ExceptionUtil.toRuntimeException(e);
        }
    }


    public static String[] addAllJarsToClassPath(String dirName) {
        if (!FileUtil.isDirectory(dirName)) {
            return null;
        }

        File dir = new File(dirName);
        List ret = CollectionUtil.newArrayList();

        File[] files = dir.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                ret.addAll(Arrays.asList(addAllJarsToClassPath(file.getAbsolutePath())));
                continue;
            }

            if (file.getName().toLowerCase().endsWith(".jar") && appendToClassPath(file.getAbsolutePath())) {
                ret.add(file.getAbsolutePath());
            }
        }

        return ret.toArray(new String[0]);
    }

    private static Manifest getManifestFromFile(File classpathItem) {

        File metaDir = new File(classpathItem, "META-INF");
        File manifestFile = null;
        if (metaDir.isDirectory()) {
            for (String m : MANIFESTS) {
                File mFile = new File(metaDir, m);
                if (mFile.isFile()) {
                    manifestFile = mFile;
                    break;
                }
            }
        }

        if (manifestFile == null) {
            return null;
        }

        return getAndClose(manifestFile);
    }

    // FIXME ExceptionUtil.toRuntimeException(e) And method name
    private static Manifest getAndClose(File manifestFile) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(manifestFile);
            return new Manifest(fis);
        } catch (IOException e) {
            throw ExceptionUtil.toRuntimeException(e);
        } finally {
            StreamUtil.close(fis);
        }
    }

    private static Manifest getManifestFromJar(File classpathItem) {

        FileInputStream fis = null;
        try {
            fis = new FileInputStream(classpathItem);
            return new JarFile(classpathItem).getManifest();
        } catch (IOException e) {
            throw new RuntimeException("JVMUtil.getManifestFromJar Error", e);
        } finally {
            StreamUtil.close(fis);
        }

    }

    public static Manifest getManifest(File classpathItem) {
        if (classpathItem == null) {
            return null;
        }

        if (classpathItem.isFile()) {
            return getManifestFromJar(classpathItem);
        }

        return getManifestFromFile(classpathItem);
    }

    private static String getClasspathItemBaseDir(File classpathItem) {

        if (classpathItem.isFile()) {
            return classpathItem.getParent();
        }

        return classpathItem.toString();
    }




    public static File[] getClasspath(ClassLoader classLoader) {
        Set classpaths = CollectionUtil.newHashSet();

        while (classLoader != null) {
            if (classLoader instanceof URLClassLoader) {
                URL[] urls = ((URLClassLoader) classLoader).getURLs();
                for (URL u : urls) {
                    File f = FileUtil.toFile(u);
                    if (f != null) {
                        try {
                            f = f.getCanonicalFile();
                            classpaths.add(f);
                            addInnerClasspathItems(classpaths, f);
                        } catch (IOException e) {
                            throw ExceptionUtil.toRuntimeException(e);
                        }
                    }
                }
            }
            classLoader = classLoader.getParent();
        }

        String bootstrap = JAVA_RUNTIME_INFO.SUN_BOOT_CLASS_PATH;
        if (bootstrap != null) {
            classpaths.add(new File(bootstrap));
        }

        return classpaths.toArray(new File[classpaths.size()]);
    }

    private static void addInnerClasspathItems(Set classpaths, File item) throws IOException {

        Manifest manifest = getManifest(item);
        if (manifest == null) {
            return;
        }

        Attributes attributes = manifest.getMainAttributes();
        if (attributes == null) {
            return;
        }

        String classPaths = attributes.getValue(Attributes.Name.CLASS_PATH);
        if (classPaths == null) {
            return;
        }

        String base = getClasspathItemBaseDir(item);

        String[] tokens = StringUtil.split(classPaths, ' ');
        for (String t : tokens) {
            File file = new File(base, t);
            file = file.getCanonicalFile();

            if (file.exists()) {
                classpaths.add(file);
            }
        }
    }

    /**
     * 取得当前运行的JRE的信息。
     *
     * @return JreInfo对象
     */
    public static final JavaRuntimeInfo getJavaRuntimeInfo() {
        return JAVA_RUNTIME_INFO;
    }

    /**
     * 代表当前运行的JRE的信息。
     */
    public static final class JavaRuntimeInfo {

        private final String SUN_BOOT_CLASS_PATH = getSystemProperty("sun.boot.class.path", false);

        private final String SUN_ARCH_DATA_MODEL = getSystemProperty("sun.arch.data.model", false);

        private final String JAVA_VENDOR_URL = getSystemProperty("java.vendor.url", false);

        /**
         * 防止从外界创建此对象。
         */
        private JavaRuntimeInfo() {
        }
        public final String getSunBootClassPath() {
            return SUN_BOOT_CLASS_PATH;
        }

        /**
         * There's no public API that allows you to distinguish between 32 and
         * 

* 64-bit operation. Think of 64-bit as just another platform in the *

* write once, run anywhere tradition. However, if you'd like to write *

* code which is platform specific (shame on you), the system property *

* sun.arch.data.model has the value "32", "64", or "unknown". * * @return 32 or 64-bit operation,if not support the property, return * unknown */ public final String getSunArchDataModel() { return SUN_ARCH_DATA_MODEL; } public final String getVendorURL() { return JAVA_VENDOR_URL; } } /** * 取得系统属性,如果因为Java安全的限制而失败,则将错误打在System.err中,然后返回 null。 * * @param name 属性名 * @param quiet 安静模式,不将出错信息打在System.err中 * * @return 属性值或null */ private static String getSystemProperty(String name, boolean quiet) { try { return System.getProperty(name); } catch (SecurityException e) { if (!quiet) { System.err.println("Caught a SecurityException reading the system property '" + name + "'; the SystemUtil property value will default to null."); } return null; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy