之前在新浪博客写了不少springmvc的相关技术,但新浪博客毕竟不是专业的技术博客,添加代码很不方便,就开始在博客园试试了。

使用java开发也不少年了,准备再次整理一些java基础知识,当然,这次不仅仅是了解一些概念,更希望能对基础知识进行更深入的原理分析。

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

以上是题外话。

学习java都会接触3个常见的名称:JDK、JRE、JVM。

来看看它们都是什么:

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;
}
}

使用代码的方式来展示是因为程序员是需要在不断的写代码中来提升的,只看技术性的文字,就没有独属于程序员的亲切感,印象不深。

BaseKnowledge.java是一个标准的java式的面向对象写法,变量私有化,通过get、set方法来访问。

现在的java开发工具(eclipse等)都具有自动生成get、set方法的功能。想起自己刚毕业参加工作时,还不熟悉开发工具,全部手写get、set方法,当私有变量很多时,可以想象那个画面。

这段代码很简单,什么都没做,就是在代码里介绍了JDK、JRE、JVM是什么。在这里只分析一下其中一句代码:

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);
}
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);
}
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);
}
}
}

这里不做更细致的分析,只是简单的贴出代码,有兴趣的可以细看。

有两点可以注意一下:

一是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);
}
}

Java基础-开篇的更多相关文章

  1. Java基础开篇

    我是一个2019毕业的非计算机的毕业生,从大二开始喜欢上Java直到现在一直都在学习,Brid从小就对计算机感兴趣,可惜高中的时候不懂事,没有规划未来,考上了一所专科学院,然后大一并不能转专业,现在毕 ...

  2. java基础总结——开篇

    工作三年多了,一直没时间静下心来好好总结,2016年马上就要过去了.也算是给自己在新一年的一个任务吧!总结java基础,然后再总结javaweb.纯属个人学习总结,总结过程中如有模糊的地方,望各位看官 ...

  3. java基础学习总结——开篇

    java是我学习的第一门编程语言,当初学习java基础的时候下了不少功夫,趁着这段时间找工作之际,好好整理一下以前学习java基础时记录的笔记,当作是对java基础学习的一个总结吧,将每一个java的 ...

  4. Java基础详解

    从写Java系列的第一篇到现在已经三个月了,因为在网络上或书籍中没有见到一些很适合初学者的学习流程,所以下决心自己写一写,也当作回顾一下Java的知识.网上有许多Java教程之类的内容,都是从概念起步 ...

  5. 转载-java基础学习汇总

    共2页: 1 2 下一页  Java制作证书的工具keytool用法总结 孤傲苍狼 2014-06-24 11:03 阅读:25751 评论:3     Java基础学习总结——Java对象的序列化和 ...

  6. Java基础知识(壹)

    写在前面的话 这篇博客,是很早之前自己的学习Java基础知识的,所记录的内容,仅仅是当时学习的一个总结随笔.现在分享出来,希望能帮助大家,如有不足的,希望大家支出. 后续会继续分享基础知识手记.希望能 ...

  7. [Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)

    如若转载请注明出处: http://www.cnblogs.com/wang-meng/p/5898837.html   谢谢.上一篇发了一个找工作的面经, 找工作不宜, 希望这一篇的内容能够帮助到大 ...

  8. 【JAVA面试题系列一】面试题总汇--JAVA基础部分

    JAVA基础 基础部分的顺序: 基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法 线程的语法,集合的语法,io 的语法,虚拟机方面的语法 每天几道,持续更新!! 1.一个". ...

  9. 最适合作为Java基础面试题之Singleton模式

    看似只是最简单的一种设计模式,可细细挖掘,static.synchronized.volatile关键字.内部类.对象克隆.序列化.枚举类型.反射和类加载机制等基础却又不易理解透彻的Java知识纷纷呼 ...

随机推荐

  1. NUMA导致的MySQL服务器SWAP问题分析

    [作者] 王栋:携程技术保障中心数据库专家,对数据库疑难问题的排查和数据库自动化智能化运维工具的开发有强烈的兴趣. [问题描述] 我们知道当mysqld进程使用到SWAP时,就会严重影响到MySQL的 ...

  2. MySQL实现Oracle rank()排序

    一.Oracle写法介绍 MySQL5.7版本没有提供类似Oracle的分析函数,比如开窗函数over(...),oracle开窗函数over(...)使用的话一般是和order.partition ...

  3. Linux下Eclipse以及Java环境安装教程[小白化](2019-9)

    Linux下安装Eclipse以及Java 一.前言 许久未用Eclipse, Ubuntu上也没装Eclipse, 今天安装发现, 好多东西都忘了. 不过经过一番查找(百度, csdn) 终于还是安 ...

  4. Android开发--Intent的使用(1)启动活动

    Android系统是目前世界上市场占有率最高的移动操作系统,近年来,Android开发也越来越炙手可热. 在Android开发中,我们使用Intent进行活动Activity之间穿梭. 当我们点击启动 ...

  5. mybatis源码专题(2)--------一起来看下使用mybatis框架的insert语句的源码执行流程吧

    本文是作者原创,版权归作者所有.若要转载,请注明出处.本文以简单的insert语句为例 1.mybatis的底层是jdbc操作,我们先来回顾一下insert语句的执行流程,如下 执行完后,我们看下数据 ...

  6. 11 (OC)* CoreImage

    coreimage framework 组成 apple 已经帮我们把image的处理分类好,来看看它的结构: 主要分为三部分: 1)定义部分:CoreImage 何CoreImageDefines. ...

  7. 如何用java实现数据脱敏

    数据脱敏是什么意思呢? 数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护.在涉及客户安全数据或者一些商业性敏感数据的情况下,在不违反系统规则条件下,对真实数据进行改造并 ...

  8. 运用 CSS in JS 实现模块化

    一.什么是 CSS in JS 上图来源:https://2019.stateofcss.com/technologies/ CSS in JS 是2014年推出的一种设计模式,它的核心思想是把 CS ...

  9. 文章导航-readme

    Spring-Boot Spring Boot(一) Hello World Redis 图解Redis之数据结构篇--简单动态字符串SDS 图解Redis之数据结构篇--链表 图解Redis之数据结 ...

  10. class命名归类

    常见class关键词: 布局类:header, footer, container, main, content, aside, page, section 包裹类:wrap, inner 区块类:r ...