java 标准库源码分析_java.lang.System源码分析
发布日期:2021-06-24 17:08:30 浏览次数:2 分类:技术文章

本文共 5451 字,大约阅读时间需要 18 分钟。

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() {

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[] 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://blog.csdn.net/weixin_34007963/article/details/114514968 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:java serializable 源码_copyserializable.java
下一篇:python输出到txt随机命名_使用Python从.txt文件中随机生成一个加权词列表

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年04月14日 12时47分50秒