目录
一、java系统的环境变量
java的main函数
hello world!是java学习课程中的第一个课,但是很多人忽略了它。因为平时得web开发是基于容器得servlet,所以初学之后很少接触它。
public static void main(String[] args){
System.out.println("Hello world!")
}
曾经我也一直好奇这个 String[] args 是做什么的?后来有人告诉我这个是用来接收外部传入参数的。比如
public class Hello{
public static void main(String[] args){
for(int i=0;i<args.length;i++){
System.out.println(args[i]);
}
}
}
通过控制台命令编译执行以上程序
#编译
javac Hello.java
#执行
java Hello a b b
#控制台输出
a
b
b
估计很多人忘记了这门手艺,没关系。我们也可以在idea eclipse等工具中配置这个传入参数
上图中Program arguments 就是main中的args。
args 在程序准备运行时用于接收外部参数可以动态的对程序进行一些配置。
args 有什么应用场景呢?
例如在springboot 项目中我要手动指定环境配置
这个时候我可以写成这样
public class Application{
public static void main(String[] args){
//当然这里可以判空或者设置默认值等,为了直观点,不写了
System.setProperty("spring.profiles.active", args[0]);
}
}
java Application dev
例如
public class Application{
public static void main(String[] args){
for(int i=0;i<args.length;i++){
String[] s=args[i].split("=");
System.out.println(s[0]+":"+s[1]);
System.setProperty(s[0], s[1]);
}
}
}
java Application spring.profiles.active=dev
当然具体怎么写看个人喜好。
System.setProperty是什么?
Java提供了System类的静态方法getenv()和getProperty()用于返回系统相关的变量与属性,getenv方法返回的变量大多于系统相关,getProperty方法返回的变量大多与java程序有关。很多框架都对系统得这两个全局变量青睐有加。
获取getProperty()
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
public class Hello{
public static void main(String[] args){
Properties properties = System.getProperties();
Iterator<Map.Entry<Object, Object>> iterator = properties.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<Object, Object> next = iterator.next();
System.out.println(next.getKey()+"="+next.getValue());
}
}
}
//获取具体某个属性
String value=System.getProperty(key)
String value=System.getenv(key)
获取getenv
import java.util.Iterator;
import java.util.Map;
public class Hello{
public static void main(String[] args){
Map<String, String> envs = System.getenv();
Iterator<Map.Entry<String, String>> iterator = envs.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<String, String> next = iterator.next();
System.out.println(next.getKey()+"="+next.getValue());
}
}
}
JVM启动参数-D的配置值放到哪里了?
jvm 启动参数
public class Hello{
public static void main(String[] args){
Properties properties = System.getProperties();
Iterator<Map.Entry<Object, Object>> iterator = properties.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<Object, Object> next = iterator.next();
System.out.println(next.getKey()+"="+next.getValue());
}
}
}
java -Dxxxxxxx=xxxxxx Hello
#控制台输出可以找到
xxxxxxx=xxxxxx
说明 加了-D参数实际上是将变量set进properties中。
这样我们在想用的地方就可以直接 getProperty(key)直接获取了。
这个两个变量具体内容就不多做介绍了,有兴趣可以自己运行以上代码看看有哪些值可以利用。
ClassLoader 是如何找到各自的类加载路径呢?
我们可以看看rt.jar 下面得classLoader.class
D:\jdk\JDK1.8_x32\jre\lib\rt.jar!\java\lang\ClassLoader.class
这个ClassLoader 加载得时候去初始化了两个系统环境变量
static void loadLibrary(Class<?> var0, String var1, boolean var2) {
ClassLoader var3 = var0 == null ? null : var0.getClassLoader();
if (sys_paths == null) {
usr_paths = initializePath("java.library.path");
sys_paths = initializePath("sun.boot.library.path");
}
//---此处省略无数行代码
}
这里实际上就是取得 getProperty()
private static String[] initializePath(String var0) {
String var1 = System.getProperty(var0, "");
//---此处省略无数行代码
}
那么我们也可以看看jvm是如何找到BoostrapClassLoader、ExtClassLoader 的加载路径,和AppClassLoader的加载路径。
我们先来看一个类sun.misc.Launcher这是jvm的一个入口,
这个类中定义了一个属性,bootClassPath是传给BoostrapClassLoader 去加载的核心类库
private static String bootClassPath = System.getProperty("sun.boot.class.path");
//此属性读取到的内容如下
/*
D:\jdk\jdk1.8.0_40\jre\lib\resources.jar;
D:\jdk\jdk1.8.0_40\jre\lib\rt.jar;
D:\jdk\jdk1.8.0_40\jre\lib\sunrsasign.jar;
D:\jdk\jdk1.8.0_40\jre\lib\jsse.jar;
D:\jdk\jdk1.8.0_40\jre\lib\jce.jar;
D:\jdk\jdk1.8.0_40\jre\lib\charsets.jar;
D:\jdk\jdk1.8.0_40\jre\lib\jfr.jar;
D:\jdk\jdk1.8.0_40\jre\classes
*/
接着来看getAppClassLoader、和ExtClassLoader
public static ClassLoader getAppClassLoader(final ClassLoader var0) throws IOException {
final String var1 = System.getProperty("java.class.path");
final File[] var2 = var1 == null ? new File[0] : Launcher.getClassPath(var1);
return (ClassLoader)AccessController.doPrivileged(new PrivilegedAction<Launcher.AppClassLoader>() {
public Launcher.AppClassLoader run() {
URL[] var1x = var1 == null ? new URL[0] : Launcher.pathToURLs(var2);
return new Launcher.AppClassLoader(var1x, var0);
}
});
}
//---此处省略无数行代码 ExtCloassLoader 也差不多不贴了
那我们来写个事例打印下看看这两个路径是什么
public class Hello{
public static void main(String[] args){
//ext ClassLoader 需要加载得包路径
System.out.println(System.getProperty("java.ext.dirs"));
//app ClassLoader 需要加载得包路径
System.out.println(System.getProperty("java.class.path"));
}
}
控制台输出
D:\jdk\jdk1.8.0_40\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext
.;D:\jdk\jdk1.8.0_40\\lib;D:\jdk\jdk1.8.0_40\\lib\tools.jar
可以看到 ExtClassLoader 加载了以下路径
D:\jdk\jdk1.8.0_40\jre\lib\ext;
C:\WINDOWS\Sun\Java\lib\ext
而 AppClassLoader则加载了以下路径
.;
D:\jdk\jdk1.8.0_40\\lib;
D:\jdk\jdk1.8.0_40\\lib\tools.jar
我们这里不分析类加载器,所以到此为止。到此总算知道几个类加载器是怎么加载类的了。