之前在新浪博客写了不少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. (1)jsoncpp库的使用

        本节主要介绍 json是什么以及jsoncpp库的使用. (1)JSON是什么 json 是一种轻量级的文本数据交换格式: json 独立于语言.平台,使用java script语法来描述对象 ...

  2. 微信小程序常用的3种弹窗

    1. 表示操作成功,文字上方会显示一个表示操作成功的图标. wx.showToast({ title: '操作成功!', icon: 'success', duration: 1500 // 提示窗停 ...

  3. Linux 笔记 - 第十一章 正则表达式

    博客地址:http://www.moonxy.com 一.前言 正则表达式(英语为 Regular Expression,在代码中常简写为 regex.regexp 或 RE),是使用单个字符串来描述 ...

  4. [Optimized Python] 17 - Performance bottle-neck

    前言 对于一门编程语言,没接触到“优化”和“库代码”的源码理解程度,不足以谈“掌握”二字. 本篇的学习笔记,同时也意味着自己终于触及到了Python的junior国际水准.(joke) 要学的东西有很 ...

  5. [Leetcode] 第324题 摆动排序II

    一.题目描述 给定一个无序的数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]... 的顺序. 示例 1: 输入: nums ...

  6. css超出多行隐藏

      单行隐藏: overflow: hidden;/*超出部分隐藏*/ text-overflow:ellipsis;/* 超出部分显示省略号 */ white-space: nowrap;/*规定段 ...

  7. Maven 创建项目之简单示例

    maven 是一个项目管理工具.可以用来管理jar包依赖,构建项目等. 那么接下来,就在eclipse中使用maven创建一个简单的项目. 1,依次点击File-> New -> Othe ...

  8. JSP常规内容

    1.forword和redirect的区别? forword是服务器请求资源,服务器直接读取URL,把目标地址URL响应读取出来,然后再把这些内容发送给浏览器.(特点是url和request sess ...

  9. Spring boot 梳理 - Spring boot 与 JSP

    若使用Spring boot 开发web应用中使用jsp,需要打包成war,并部署到非嵌入式servlet容器中运行,在嵌入式servlet中无法运行,且需要匹配非嵌入式servlet版本与Sprin ...

  10. linux服务器创建虚拟路径解决文件上传路径隔离问题

    需求环境 图片上传最简单的就是上传web项目下,这样图片与项目不可分离会产生很多不必要的影响.例如:重新部署项目需要把所有上传的图片再copy一份等. 图片与项目分离有好几种方式: 方式一.在linu ...