简介

  • System类,是Java中一个比较常用的类,其使用到的方法也比较少。
  • 我们直接从代码看起

    源码阅读

    1. public final class System {
    2. private static native void registerNatives();
    3. static {
    4. registerNatives();
    5. }
    6. // 私有构造器
    7. private System() {
    8. }
    9. // 输入流
    10. public final static InputStream in = null;
    11. // 输出流
    12. public final static PrintStream out = null;
    13. // 输出流
    14. public final static PrintStream err = null;
    15. // 系统的安全管理器
    16. private static volatile SecurityManager security = null;
    17. // 重新分配“标准”输入流。
    18. public static void setIn(InputStream in) {
    19. checkIO();
    20. setIn0(in);
    21. }
    22. // 重新分配“标准”输出流
    23. public static void setOut(PrintStream out) {
    24. checkIO();
    25. setOut0(out);
    26. }
    27. // 重新分配“标准”输出流
    28. public static void setErr(PrintStream err) {
    29. checkIO();
    30. setErr0(err);
    31. }
    32. private static volatile Console cons = null;
    33. public static Console console() {
    34. if (cons == null) {
    35. synchronized (System.class) {
    36. cons = sun.misc.SharedSecrets.getJavaIOAccess().console();
    37. }
    38. }
    39. return cons;
    40. }
    41. // 管道流
    42. public static Channel inheritedChannel() throws IOException {
    43. return SelectorProvider.provider().inheritedChannel();
    44. }
    45. // 安全管理 IO
    46. private static void checkIO() {
    47. SecurityManager sm = getSecurityManager();
    48. if (sm != null) {
    49. sm.checkPermission(new RuntimePermission("setIO"));
    50. }
    51. }
    52. // 本地方法
    53. private static native void setIn0(InputStream in);
    54. private static native void setOut0(PrintStream out);
    55. private static native void setErr0(PrintStream err);
    56. // 设置安全管理器
    57. public static void setSecurityManager(final SecurityManager s) {
    58. try {
    59. s.checkPackageAccess("java.lang");
    60. } catch (Exception e) {
    61. // no-op
    62. }
    63. setSecurityManager0(s);
    64. }
    65. //
    66. private static synchronized void setSecurityManager0(final SecurityManager s) {
    67. SecurityManager sm = getSecurityManager();
    68. if (sm != null) {
    69. sm.checkPermission(new RuntimePermission
    70. ("setSecurityManager"));
    71. }
    72. if ((s != null) && (s.getClass().getClassLoader() != null)) {
    73. AccessController.doPrivileged(new PrivilegedAction<Object>() {
    74. public Object run() {
    75. s.getClass().getProtectionDomain().implies
    76. (SecurityConstants.ALL_PERMISSION);
    77. return null;
    78. }
    79. });
    80. }
    81. security = s;
    82. }
    83. // 获取安全管理器
    84. public static SecurityManager getSecurityManager() {
    85. return security;
    86. }
    87. // 本地方法 获取从 1970年1月1日0点0分0秒 到当前之间的毫秒数
    88. public static native long currentTimeMillis();
    89. // 本地方法 获取从 1970年1月1日0点0分0秒 到当前之间的纳秒数
    90. public static native long nanoTime();
    91. // 本地方法 ,执行数组的拷贝
    92. // 第一个参数 需要拷贝的数组,
    93. // 第二个参数 需要拷贝的数组的开始下标
    94. // 第三个参数 需要拷贝到的数组
    95. // 第四个参数 需要拷贝到的数组的开始下标
    96. // 第五个参数 需要拷贝的个数
    97. public static native void arraycopy(Object src, int srcPos,
    98. Object dest, int destPos,
    99. int length);
    100. // 返回给定对象相同的哈希码会被默认的方法hashCode()方法返回
    101. // 给定对象的与否类重写hashCode() 为空引用的哈希码是零。
    102. public static native int identityHashCode(Object x);
    103. // Properties对象
    104. private static Properties props;
    105. // 初始化 Properties 对象
    106. private static native Properties initProperties(Properties props);
    107. // 获取Properties对象
    108. public static Properties getProperties() {
    109. SecurityManager sm = getSecurityManager();
    110. if (sm != null) {
    111. sm.checkPropertiesAccess();
    112. }
    113. return props;
    114. }
    115. // 分隔器
    116. public static String lineSeparator() {
    117. return lineSeparator;
    118. }
    119. private static String lineSeparator;
    120. // 设置外部传入的 Properties 对象
    121. public static void setProperties(Properties props) {
    122. SecurityManager sm = getSecurityManager();
    123. if (sm != null) {
    124. sm.checkPropertiesAccess();
    125. }
    126. if (props == null) {
    127. props = new Properties();
    128. initProperties(props);
    129. }
    130. System.props = props;
    131. }
    132. // 通过key或者当前对象的 Properties 对象的key
    133. public static String getProperty(String key) {
    134. checkKey(key);
    135. SecurityManager sm = getSecurityManager();
    136. if (sm != null) {
    137. sm.checkPropertyAccess(key);
    138. }
    139. return props.getProperty(key);
    140. }
    141. // 根据 k v 获取
    142. public static String getProperty(String key, String def) {
    143. checkKey(key);
    144. SecurityManager sm = getSecurityManager();
    145. if (sm != null) {
    146. sm.checkPropertyAccess(key);
    147. }
    148. return props.getProperty(key, def);
    149. }
    150. // 设置 k v
    151. public static String setProperty(String key, String value) {
    152. checkKey(key);
    153. SecurityManager sm = getSecurityManager();
    154. if (sm != null) {
    155. sm.checkPermission(new PropertyPermission(key,
    156. SecurityConstants.PROPERTY_WRITE_ACTION));
    157. }
    158. return (String) props.setProperty(key, value);
    159. }
    160. // 删除 某个key
    161. public static String clearProperty(String key) {
    162. checkKey(key);
    163. SecurityManager sm = getSecurityManager();
    164. if (sm != null) {
    165. sm.checkPermission(new PropertyPermission(key, "write"));
    166. }
    167. return (String) props.remove(key);
    168. }
    169. // 辅助方法
    170. private static void checkKey(String key) {
    171. if (key == null) {
    172. throw new NullPointerException("key can't be null");
    173. }
    174. if (key.equals("")) {
    175. throw new IllegalArgumentException("key can't be empty");
    176. }
    177. }
    178. // 获得指定的环境变量的值。 环境变量是一个依赖于系统的外部命名的值
    179. public static String getenv(String name) {
    180. SecurityManager sm = getSecurityManager();
    181. if (sm != null) {
    182. sm.checkPermission(new RuntimePermission("getenv."+name));
    183. }
    184. return ProcessEnvironment.getenv(name);
    185. }
    186. // 获得指定的环境变量的键值对Map对象
    187. public static java.util.Map<String,String> getenv() {
    188. SecurityManager sm = getSecurityManager();
    189. if (sm != null) {
    190. sm.checkPermission(new RuntimePermission("getenv.*"));
    191. }
    192. return ProcessEnvironment.getenv();
    193. }
    194. // 退出程序的方法
    195. public static void exit(int status) {
    196. Runtime.getRuntime().exit(status);
    197. }
    198. // 调用gc方法,但是JVM不一定立即执行GC
    199. public static void gc() {
    200. Runtime.getRuntime().gc();
    201. }
    202. // 运行挂起终止的任何对象的终止方法。
    203. public static void runFinalization() {
    204. Runtime.getRuntime().runFinalization();
    205. }
    206. // 终止方法 已经过时
    207. public static void runFinalizersOnExit(boolean value) {
    208. Runtime.runFinalizersOnExit(value);
    209. }
    210. // 加载一个文件
    211. public static void load(String filename) {
    212. Runtime.getRuntime().load0(Reflection.getCallerClass(), filename);
    213. }
    214. // 加载类包
    215. public static void loadLibrary(String libname) {
    216. Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);
    217. }
    218. // 调用本地方法 根据类包获取名字 win10 下是 包的dll文件
    219. public static native String mapLibraryName(String libname);
    220. // 获取一个打印流
    221. private static PrintStream newPrintStream(FileOutputStream fos, String enc) {
    222. if (enc != null) {
    223. try {
    224. return new PrintStream(new BufferedOutputStream(fos, 128), true, enc);
    225. } catch (UnsupportedEncodingException uee) {}
    226. }
    227. return new PrintStream(new BufferedOutputStream(fos, 128), true);
    228. }
    229. // System类的初始化
    230. private static void initializeSystemClass() {
    231. props = new Properties();
    232. initProperties(props); // initialized by the VM
    233. sun.misc.VM.saveAndRemoveProperties(props);
    234. lineSeparator = props.getProperty("line.separator");
    235. sun.misc.Version.init();
    236. FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
    237. FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
    238. FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
    239. setIn0(new BufferedInputStream(fdIn));
    240. setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding")));
    241. setErr0(newPrintStream(fdErr, props.getProperty("sun.stderr.encoding")));
    242. loadLibrary("zip");
    243. Terminator.setup();
    244. sun.misc.VM.initializeOSEnvironment();
    245. Thread current = Thread.currentThread();
    246. current.getThreadGroup().add(current);
    247. setJavaLangAccess();
    248. sun.misc.VM.booted();
    249. }
    250. //
    251. private static void setJavaLangAccess() {
    252. // Allow privileged classes outside of java.lang
    253. sun.misc.SharedSecrets.setJavaLangAccess(new sun.misc.JavaLangAccess(){
    254. public sun.reflect.ConstantPool getConstantPool(Class<?> klass) {
    255. return klass.getConstantPool();
    256. }
    257. public boolean casAnnotationType(Class<?> klass, AnnotationType oldType, AnnotationType newType) {
    258. return klass.casAnnotationType(oldType, newType);
    259. }
    260. public AnnotationType getAnnotationType(Class<?> klass) {
    261. return klass.getAnnotationType();
    262. }
    263. public Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationMap(Class<?> klass) {
    264. return klass.getDeclaredAnnotationMap();
    265. }
    266. public byte[] getRawClassAnnotations(Class<?> klass) {
    267. return klass.getRawAnnotations();
    268. }
    269. public byte[] getRawClassTypeAnnotations(Class<?> klass) {
    270. return klass.getRawTypeAnnotations();
    271. }
    272. public byte[] getRawExecutableTypeAnnotations(Executable executable) {
    273. return Class.getExecutableTypeAnnotationBytes(executable);
    274. }
    275. public <E extends Enum<E>>
    276. E[] getEnumConstantsShared(Class<E> klass) {
    277. return klass.getEnumConstantsShared();
    278. }
    279. public void blockedOn(Thread t, Interruptible b) {
    280. t.blockedOn(b);
    281. }
    282. public void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook) {
    283. Shutdown.add(slot, registerShutdownInProgress, hook);
    284. }
    285. public int getStackTraceDepth(Throwable t) {
    286. return t.getStackTraceDepth();
    287. }
    288. public StackTraceElement getStackTraceElement(Throwable t, int i) {
    289. return t.getStackTraceElement(i);
    290. }
    291. public String newStringUnsafe(char[] chars) {
    292. return new String(chars, true);
    293. }
    294. public Thread newThreadWithAcc(Runnable target, AccessControlContext acc) {
    295. return new Thread(target, acc);
    296. }
    297. public void invokeFinalize(Object o) throws Throwable {
    298. o.finalize();
    299. }
    300. });
    301. }
    302. }

    常用的方法

  • 如果我们需要在项目启动的时候,设置运行环境,我们就可以读取配置,然后写入 ```java public class SystemTest { public static void main(String[] args) {

      String s = System.setProperty("key", "value");
      System.out.println(s);
      System.out.println(System.getProperty("key"));
    

    } }

```

  • 获取时间、获取纳秒等等

    总结

  • 在面试中我们会遇到一些题目 比如:System.out.println(); 的原理,因为System类里面封装了PrintStream类、InputStream类等

  • 同样的,在System类中也封装了 Runtime类、Properties类的对象