Java基础-开篇
之前在新浪博客写了不少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基础-开篇的更多相关文章
- Java基础开篇
我是一个2019毕业的非计算机的毕业生,从大二开始喜欢上Java直到现在一直都在学习,Brid从小就对计算机感兴趣,可惜高中的时候不懂事,没有规划未来,考上了一所专科学院,然后大一并不能转专业,现在毕 ...
- java基础总结——开篇
工作三年多了,一直没时间静下心来好好总结,2016年马上就要过去了.也算是给自己在新一年的一个任务吧!总结java基础,然后再总结javaweb.纯属个人学习总结,总结过程中如有模糊的地方,望各位看官 ...
- java基础学习总结——开篇
java是我学习的第一门编程语言,当初学习java基础的时候下了不少功夫,趁着这段时间找工作之际,好好整理一下以前学习java基础时记录的笔记,当作是对java基础学习的一个总结吧,将每一个java的 ...
- Java基础详解
从写Java系列的第一篇到现在已经三个月了,因为在网络上或书籍中没有见到一些很适合初学者的学习流程,所以下决心自己写一写,也当作回顾一下Java的知识.网上有许多Java教程之类的内容,都是从概念起步 ...
- 转载-java基础学习汇总
共2页: 1 2 下一页 Java制作证书的工具keytool用法总结 孤傲苍狼 2014-06-24 11:03 阅读:25751 评论:3 Java基础学习总结——Java对象的序列化和 ...
- Java基础知识(壹)
写在前面的话 这篇博客,是很早之前自己的学习Java基础知识的,所记录的内容,仅仅是当时学习的一个总结随笔.现在分享出来,希望能帮助大家,如有不足的,希望大家支出. 后续会继续分享基础知识手记.希望能 ...
- [Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)
如若转载请注明出处: http://www.cnblogs.com/wang-meng/p/5898837.html 谢谢.上一篇发了一个找工作的面经, 找工作不宜, 希望这一篇的内容能够帮助到大 ...
- 【JAVA面试题系列一】面试题总汇--JAVA基础部分
JAVA基础 基础部分的顺序: 基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法 线程的语法,集合的语法,io 的语法,虚拟机方面的语法 每天几道,持续更新!! 1.一个". ...
- 最适合作为Java基础面试题之Singleton模式
看似只是最简单的一种设计模式,可细细挖掘,static.synchronized.volatile关键字.内部类.对象克隆.序列化.枚举类型.反射和类加载机制等基础却又不易理解透彻的Java知识纷纷呼 ...
随机推荐
- 在eclipse中引入mybatis和spring的约束文件
eclipse中引入mybatis约束文件步骤: 首先: config的key值 http://mybatis.org/dtd/mybatis-3-config.dtd mapper的key值 htt ...
- JVM学习(虚拟机栈、堆、方法区)自我看法
堆(Heap): 此内存区域唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配.这一点在java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配. 虚拟机栈(Stack): 虚拟机栈主 ...
- 基于LeNet的手写汉字识别(caffe)
我假设已经成功编译caffe,如果没有,请参考http://caffe.berkeleyvision.org/installation.html 在本教程中,我假设你的caffe安装目录是CAFFE_ ...
- Day 14 查找文件 find
find 查找方式 1.按照名称进行查找 [root@oldboyedu ~]# find ./ -name "*eth0" 2.按照名称查找(不区分大小写) [root@oldb ...
- UVM——寄存器模型相关的一些函数
0. 引言 在UVM支持的寄存器操作中,有get.update.mirror.write等等一些方法,在这里整理一下他们的用法. 寄存器模型中的寄存器值应该与DUT保持同步,但是由于DUT的值是实时更 ...
- 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU硬件那些事(1)- 官方EVK简介
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列MCU的配套EVK板. 半导体设计厂商发布任何一块MCU芯片新品,一般都会同步推出基于这款MCU的配套 ...
- 品Spring:SpringBoot轻松取胜bean定义注册的“第一阶段”
上一篇文章强调了bean定义注册占Spring应用的半壁江山.而且详细介绍了两个重量级的注册bean定义的类. 今天就以SpringBoot为例,来看看整个SpringBoot应用的bean定义是如何 ...
- Spring 梳理-数据访问-DB
针对接口编程 DAO是指数据访问对象(data access object),它提供了数据读取和写入到数据库中的一种方式.Spring认为,它应该以接口的方式发布功能,而应用程序的其他部分需要通过接口 ...
- Linux下查看版本信息
Linux下如何查看版本信息, 包括位数.版本信息以及CPU内核信息.CPU具体型号等. 1.# uname -a (Linux查看版本当前操作系统内核信息) 2.# cat /proc/ ...
- centos7 远程连接其他服务器redis
在本地远程连接 在终端输入: redis-cli -h 服务器ip地址 -p 端口 -a 密码