您现在的位置是:首页 > 文章详情

java.lang.System源码分析

日期:2018-08-26点击:192

1.final修饰,不能被继承。构造函数使用private修饰,不能被其他类实例化

    public final class System {         ...         private System() {         }         ...     }

2.成员变量:final修饰,不能被重新赋值    

 public final static InputStream in = null;// 标准输入流,默认已经打开,一般用来响应键盘或者其他用户指定的输入     public final static PrintStream out = null;// 标准输出流,默认已经打开,一般用来展示输出     public final static PrintStream err = null;// 标准错误输出流,默认已经打开,按照约定,用来输出错误信息     private static native void setIn0(InputStream in);// 初始化这些流的工作由本地native方法实现,由系统连接的共享库去实现     private static native void setOut0(PrintStream out);     private static native void setErr0(PrintStream err); private static volatile SecurityManager security = null;// 系统安全管理器,使用volatile修饰该变量。在初始化IO流时,需要使用安全器校验权限     private static volatile Console cons = null;// 标准输出控制台

3.SecurityManager,安全管理器,用来做访问权限校验

 public static void setSecurityManager(final SecurityManager s) {         try {             s.checkPackageAccess("java.lang");         } catch (Exception e) {             // no-op         }         setSecurityManager0(s);     }     private static synchronized void setSecurityManager0(final SecurityManager s) {         SecurityManager sm = getSecurityManager();         if (sm != null) {             // ask the currently installed security manager if we             // can replace it.             sm.checkPermission(new RuntimePermission("setSecurityManager"));         }         if ((s != null) && (s.getClass().getClassLoader() != null)) {             // New security manager class is not on bootstrap classpath.             // Cause policy to get initialized before we install the new             // security manager, in order to prevent infinite loops when             // trying to initialize the policy (which usually involves             // accessing some security and/or system properties, which in turn             // calls the installed security manager's checkPermission method             // which will loop infinitely if there is a non-system class             // (in this case: the new security manager class) on the stack).             AccessController.doPrivileged(new PrivilegedAction<Object>() {                 public Object run() {                     s.getClass().getProtectionDomain().implies                         (SecurityConstants.ALL_PERMISSION);                     return null;                 }             });         }         security = s;     }     private static void checkIO() {         SecurityManager sm = getSecurityManager();         if (sm != null) {             sm.checkPermission(new RuntimePermission("setIO"));         }     }     public void checkPermission(Permission perm) {         java.security.AccessController.checkPermission(perm);     }

4.Console 只能用在标准输入、输出流未被重定向的原始控制台中使用

 public static Console console() {          if (cons == null) {              synchronized (System.class) {                  cons = sun.misc.SharedSecrets.getJavaIOAccess().console();// console是通过sun.misc.SharedSecrets 类获取得到的(作用是从JVM里面获取实例对象)              }          }          return cons;      }

5.获取系统时间,都是通过本地native方法实现

    public static native long currentTimeMillis();// 获取毫秒级的时间戳(1970年1月1日0时起的毫秒数)     public static native long nanoTime();// 获取纳秒,返回的可能是任意时间(主要用于衡量时间段)

6.数组拷贝

public static native void arraycopy(Object src,  int  srcPos,Object dest, int destPos,int length);

    此方法在Collection的实现类里面扩容的时候经常被遇到,例如 ArrayList.add(int, E)。

    还有另外一个比较常用的数组拷贝的方法:Arrays.copyOf,通过看源码会发现,最后实际调用的也是 Syetem.arraycopy 。    

 public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {         @SuppressWarnings("unchecked")         T[] copy = ((Object)newType == (Object)Object[].class)             ? (T[]) new Object[newLength]             : (T[]) Array.newInstance(newType.getComponentType(), newLength);         System.arraycopy(original, 0, copy, 0,                          Math.min(original.length, newLength));         return copy;     }

7.获取对象的地址,本地native方法

public static native int identityHashCode(Object x);

    当Object的hashCode()被重写的时候,如何获取到对象的地址呢?通过 System.identityHashCode(Object) 可以获取到对象的地址。

public class OverrideHashCode {        @Override        public int hashCode() {              //return super.hashCode();              return 0;        } } OverrideHashCode overrideHash = new OverrideHashCode(); System.out.println("覆盖之后,hashCode(): " + overrideHash.hashCode()); System.out.println("通过System.identityHashCode()重新获取对象地址: " + System.identityHashCode(overrideHash));

    测试结果:

覆盖之后,hashCode(): 2018699554 // 未被重写 通过System.identityHashCode()重新获取对象地址: 2018699554 覆盖之后,hashCode(): 0 // 重写后的值 通过System.identityHashCode()重新获取对象地址: 2018699554

8.系统变量

 private static Properties props;     private static native Properties initProperties(Properties props);// 初始化是通过本地方法实现的     public static Properties getProperties() {         SecurityManager sm = getSecurityManager();         if (sm != null) {// 获取系统变量的时候,需要做权限校验。如果没有权限,会抛出 AccessControlException              sm.checkPropertiesAccess();         }         return props;     }     public static void setProperties(Properties props) {         SecurityManager sm = getSecurityManager();         if (sm != null) {             sm.checkPropertiesAccess();         }         if (props == null) {             props = new Properties();             initProperties(props);         }         System.props = props;     }

9.获取操作系统环境变量,用户自己配置的系统变量,也做了权限校验

 public static String getenv(String name) {         SecurityManager sm = getSecurityManager();         if (sm != null) {             sm.checkPermission(new RuntimePermission("getenv."+name));         }         return ProcessEnvironment.getenv(name);     }

    测试使用:

System.out.println(System.getenv("ROCKETMQ_HOME"));

    能够获取,之前在Windows中设置的环境变量的值。

10.程序退出,接收一个参数status,0表示正常退出,非零参数表示非正常退出。不管status为何值都会退出程序。和return 相比,return是回到上一层,而System.exit(status)是回到最上层

 public static void exit(int status) {         Runtime.getRuntime().exit(status);// 实际上通过获取Runtime运行时来退出的     }

11.手动调用gc-垃圾回收器,注意调用后不会马上发生消息回收,JVM会在适合的时候触发GC

 public static void gc() {         Runtime.getRuntime().gc();     }

12.加载动态库(Windows下面是dll文件),用来装载库文件,不论是JNI库文件还是非JNI库文件

 @CallerSensitive     public static void load(String filename) {// fileName一定要是绝对路径,否则会抛出 UnsatisfiedLinkError         Runtime.getRuntime().load0(Reflection.getCallerClass(), filename);     }     @CallerSensitive     public static void loadLibrary(String libname) {         Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);     }
    好了,Syetem的代码就这么多~
原文链接:https://yq.aliyun.com/articles/629406
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章