Java基礎-開篇

以前在新浪博客寫了很多springmvc的相關技術,但新浪博客畢竟不是專業的技術博客,添加代碼很不方便,就開始在博客園試試了。java

使用java開發也很多年了,準備再次整理一些java基礎知識,固然,此次不只僅是瞭解一些概念,更但願能對基礎知識進行更深刻的原理分析。linux

————————————————————————————————————————————————————————————————程序員

以上是題外話。spring

學習java都會接觸3個常見的名稱:JDK、JRE、JVM。windows

來看看它們都是什麼:安全

package com.yun.jvm; /** * Base Knowledge * @author Mars * */
public class BaseKnowledge { private static final String LINE_SEPARATOR = "line.separator"; /** * Java Development Kit * java的開發工具,包括jre+開發工具 */
    private String jdk = 
            "JDK:" + System.getProperty(LINE_SEPARATOR) + "Java Development Kit;" + System.getProperty(LINE_SEPARATOR) + "java的開發工具,包括jre+開發工具" + System.getProperty(LINE_SEPARATOR); /** * Java Runtime Environment * java的運行環境,包括jvm+java的核心類庫 */
    private String jre = 
            "JRE:" + System.getProperty(LINE_SEPARATOR) + "Java Runtime Environment;" + System.getProperty(LINE_SEPARATOR) + "java的運行環境,包括jvm+java的核心類庫" + System.getProperty(LINE_SEPARATOR); /** * Java Virtual Machine * java虛擬機,用於保證java的跨平臺的特性 * Java語言使用Java虛擬機屏蔽了與具體平臺相關的信息, * 使得Java語言編譯程序只需生成在Java虛擬機上運行的目標代碼(字節碼), * 就能夠在多種平臺上不加修改地運行。 * Java虛擬機在執行字節碼時,把字節碼解釋成具體平臺上的機器指令執行 */
    private String jvm = 
            "JVM:" + System.getProperty(LINE_SEPARATOR) + "Java Virtual Machine;" + System.getProperty(LINE_SEPARATOR) + "java虛擬機,用於保證java的跨平臺的特性;" + System.getProperty(LINE_SEPARATOR) + "Java語言使用Java虛擬機屏蔽了與具體平臺相關的信息," + System.getProperty(LINE_SEPARATOR) + "使得Java語言編譯程序只需生成在Java虛擬機上運行的目標代碼(字節碼)," + System.getProperty(LINE_SEPARATOR) + "就能夠在多種平臺上不加修改地運行。" + System.getProperty(LINE_SEPARATOR) + "Java虛擬機在執行字節碼時,把字節碼解釋成具體平臺上的機器指令執行" + System.getProperty(LINE_SEPARATOR); public String getJdk() { return jdk; } public void setJdk(String jdk) { this.jdk = jdk; } public String getJre() { return jre; } public void setJre(String jre) { this.jre = jre; } public String getJvm() { return jvm; } public void setJvm(String jvm) { this.jvm = jvm; } }
View Code

使用代碼的方式來展現是由於程序員是須要在不斷的寫代碼中來提高的,只看技術性的文字,就沒有獨屬於程序員的親切感,印象不深。mvc

BaseKnowledge.java是一個標準的java式的面向對象寫法,變量私有化,經過get、set方法來訪問。app

如今的java開發工具(eclipse等)都具備自動生成get、set方法的功能。想起本身剛畢業參加工做時,還不熟悉開發工具,所有手寫get、set方法,當私有變量不少時,能夠想象那個畫面。dom

這段代碼很簡單,什麼都沒作,就是在代碼裏介紹了JDK、JRE、JVM是什麼。在這裏只分析一下其中一句代碼:eclipse

System.getProperty(LINE_SEPARATOR)

這句代碼是從系統中獲取當前操做系統的換行符,不一樣操做系統的換行符是不同的,好比windows系統是/r/n,linux系統是/n,蘋果機系統是/r。

使用這句代碼能夠避免硬編碼帶來的不一樣操做系統可能產生的問題,也省去了手動進行不一樣操做系統的分支判斷。

public static String getProperty(String key) { checkKey(key); SecurityManager sm = getSecurityManager(); if (sm != null) { sm.checkPropertyAccess(key); } return props.getProperty(key); }

這個方法屬於java.lang.System類。

1.checkKey方法,判斷key是否爲空值,若是是空值,直接拋出異常。

private static void checkKey(String key) { if (key == null) { throw new NullPointerException("key can't be null"); } if (key.equals("")) { throw new IllegalArgumentException("key can't be empty"); } }

注意這裏的邏輯處理方式,是經過拋異常的方式來處理key值爲空的狀況,而不是另一種boolean判斷方法:

private static boolean checkKey(String key) { if (key == null || key.equals("")) { return false; } return true; } public static String getProperty(String key) { if (checkKey(key)) { // do sth..
 } return null; }

我的以爲不少時候程序員寫代碼都對java的異常處理Exception關注不夠,筆者參與的不少項目也沒有對Exception有比較規範成體系的處理。

這兩種寫法在具體的項目開發中,值得去思考一下如何選擇。

2.獲取SecurityManager,校驗當前的key在操做系統安全策略裏是否是可訪問的。

SecurityManager sm = getSecurityManager(); if (sm != null) { sm.checkPropertyAccess(key); }

一層層向下看:

public void checkPropertyAccess(String key) { checkPermission(new PropertyPermission(key, SecurityConstants.PROPERTY_READ_ACTION)); }
public void checkPermission(Permission perm) { java.security.AccessController.checkPermission(perm); }
public static void checkPermission(Permission perm) throws AccessControlException { //System.err.println("checkPermission "+perm); //Thread.currentThread().dumpStack();

        if (perm == null) { throw new NullPointerException("permission can't be null"); } AccessControlContext stack = getStackAccessControlContext(); // if context is null, we had privileged system code on the stack.
        if (stack == null) { Debug debug = AccessControlContext.getDebug(); boolean dumpDebug = false; if (debug != null) { dumpDebug = !Debug.isOn("codebase="); dumpDebug &= !Debug.isOn("permission=") || Debug.isOn("permission=" + perm.getClass().getCanonicalName()); } if (dumpDebug && Debug.isOn("stack")) { Thread.dumpStack(); } if (dumpDebug && Debug.isOn("domain")) { debug.println("domain (context is null)"); } if (dumpDebug) { debug.println("access allowed "+perm); } return; } AccessControlContext acc = stack.optimize(); acc.checkPermission(perm); }
View Code
public void checkPermission(Permission perm) throws AccessControlException { boolean dumpDebug = false; if (perm == null) { throw new NullPointerException("permission can't be null"); } if (getDebug() != null) { // If "codebase" is not specified, we dump the info by default.
            dumpDebug = !Debug.isOn("codebase="); if (!dumpDebug) { // If "codebase" is specified, only dump if the specified code // value is in the stack.
                for (int i = 0; context != null && i < context.length; i++) { if (context[i].getCodeSource() != null && context[i].getCodeSource().getLocation() != null && Debug.isOn("codebase=" + context[i].getCodeSource().getLocation().toString())) { dumpDebug = true; break; } } } dumpDebug &= !Debug.isOn("permission=") || Debug.isOn("permission=" + perm.getClass().getCanonicalName()); if (dumpDebug && Debug.isOn("stack")) { Thread.dumpStack(); } if (dumpDebug && Debug.isOn("domain")) { if (context == null) { debug.println("domain (context is null)"); } else { for (int i=0; i< context.length; i++) { debug.println("domain "+i+" "+context[i]); } } } } /* * iterate through the ProtectionDomains in the context. * Stop at the first one that doesn't allow the * requested permission (throwing an exception). * */

        /* if ctxt is null, all we had on the stack were system domains, or the first domain was a Privileged system domain. This is to make the common case for system code very fast */

        if (context == null) { checkPermission2(perm); return; } for (int i=0; i< context.length; i++) { if (context[i] != null &&  !context[i].implies(perm)) { if (dumpDebug) { debug.println("access denied " + perm); } if (Debug.isOn("failure") && debug != null) { // Want to make sure this is always displayed for failure, // but do not want to display again if already displayed // above.
                    if (!dumpDebug) { debug.println("access denied " + perm); } Thread.dumpStack(); final ProtectionDomain pd = context[i]; final Debug db = debug; AccessController.doPrivileged (new PrivilegedAction<Void>() { public Void run() { db.println("domain that failed "+pd); return null; } }); } throw new AccessControlException("access denied "+perm, perm); } } // allow if all of them allowed access
        if (dumpDebug) { debug.println("access allowed "+perm); } checkPermission2(perm); }
View Code
private void checkPermission2(Permission perm) { if (!isLimited) { return; } /* * Check the doPrivileged() context parameter, if present. */
        if (privilegedContext != null) { privilegedContext.checkPermission2(perm); } /* * Ignore the limited permissions and parent fields of a wrapper * context since they were already carried down into the unwrapped * context. */
        if (isWrapped) { return; } /* * Try to match any limited privilege scope. */
        if (permissions != null) { Class<?> permClass = perm.getClass(); for (int i=0; i < permissions.length; i++) { Permission limit = permissions[i]; if (limit.getClass().equals(permClass) && limit.implies(perm)) { return; } } } /* * Check the limited privilege scope up the call stack or the inherited * parent thread call stack of this ACC. */
        if (parent != null) { /* * As an optimization, if the parent context is the inherited call * stack context from a parent thread then checking the protection * domains of the parent context is redundant since they have * already been merged into the child thread's context by * optimize(). When parent is set to an inherited context this * context was not directly created by a limited scope * doPrivileged() and it does not have its own limited permissions. */
            if (permissions == null) { parent.checkPermission2(perm); } else { parent.checkPermission(perm); } } }
View Code

這裏不作更細緻的分析,只是簡單的貼出代碼,有興趣的能夠細看。

有兩點能夠注意一下:

一是checkPermission方法裏對於沒有訪問權限的key,一樣是經過拋出異常的方式來處理,而不是返回true or false;

二是有個checkPermission2的方法,按理說這種命名方式是不可取的,不符合命名規範,不知道是否是由於代碼是反編譯出來的緣由。

(注:貼出的代碼屬於java.security.AccessController和java.security.AccessControlContext類)

3.通過非空判斷和訪問權限校驗後,從props裏獲取具體的key對應的value

return props.getProperty(key);

props是System類的成員變量,會在JVM啓動時進行初始化:

private static void initializeSystemClass() { // VM might invoke JNU_NewStringPlatform() to set those encoding // sensitive properties (user.home, user.name, boot.class.path, etc.) // during "props" initialization, in which it may need access, via // System.getProperty(), to the related system encoding property that // have been initialized (put into "props") at early stage of the // initialization. So make sure the "props" is available at the // very beginning of the initialization and all system properties to // be put into it directly.
        props = new Properties(); initProperties(props); // initialized by the VM
private static native Properties initProperties(Properties props);
initProperties是一個本地(native)方法。

System.getProperty()方法就分析到這裏了,能夠看出,到處都是知識點啊,很簡單的代碼,它背後的東西每每不簡單;固然,若是細細的分析清楚了,那麼再複雜的代碼,在程序員眼裏,也會很簡單。

——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
分割線。

接下來準備對java程序運行的根本,JVM,進行比較詳細的分析。弄清楚JVM的原理,對咱們寫代碼和程序優化,都會有很是大的幫助。

 ——————————————————————————————————————————————————————————————————

package com.yun.jvm;

/**
 * Main
 * @author Mars
 *
 */
public class Main {

    /**
     * main method
     * @param args
     */
    public static void main(String[] args) {
        
        // baseKnowledge
        BaseKnowledge baseKnowledge = new BaseKnowledge();
        
        // jdk
        String jdk = baseKnowledge.getJdk();
        
        // jre
        String jre = baseKnowledge.getJre();
        
        // jvm
        String jvm = baseKnowledge.getJvm();
        
        // output
        System.out.println("My dear, my wife, I love you !");
        System.out.println(jdk);
        System.out.println(jre);
        System.out.println(jvm);
    }
}
View Code
相關文章
相關標籤/搜索