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
相关文章
相关标签/搜索