java中的运行环境
文章目录
- 一.前言
- 二.环境变量
- 使用win+R来快速打开文件
- 三.JVM变量
- 四.classpath
- END
一.前言
任何程序运行需要一个运行环境,这是非常重要的概念.首先我们应该明确,运行环境是什么?
现在计算机模型中,程序都运行在操作系统,由操作系统进行软件的管理,那么显然,操作系统本身是所有程序的运行环境.但是有些程序不是直接运行在操作系统上的.比如java,python,他们都有自己的解释器,先编译成解释器可以看懂的文件再由解释器来运行.解释器也是运行环境.
在java的程序中,首先我们需要启动jvm然后由jvm启动classloader来载入class文件.在jvm的类加载器中,AppClassLoader会加载类路径(classpath)下的文件到环境中.
所以对于java程序,环境包括操作系统,jvm以及classpath.
二.环境变量
首先要提操作系统的环境变量,而环境变量是操作系统中的变量,任何程序运行时都能从中获取他们.这也就是一些java开发的工具必须配置JAVA_HOME的原因.
win10中环境变量与对应的作用:
%APPDATA%
登录用户的应用程序数据保存的路径.默认是C:\Users%USER%\AppData\Roaming
%LOCALAPPDATA%
本地应用的程序数据的保存路径,包括桌面主题,系统报告,浏览器的缓存等.
C:\Users%USER%\AppData\Local
%ComSpec%
cmd的全路径,默认C:\windows\system32\cmd.exe
%OS%
操作系统内核的名字.默认是Windows_NT
%PATH%
这个变量的值是以分号分隔的路径列表.命令行会从这个这个变量中搜索与指定命令匹配的可执行文件
但是不仅如此,我们可以在命令行输入start或者win+R来运行打开可以双击的对象,这包括可执行文件,快捷方式,文件夹,具有默认打开方式的各种文件(文本文件,媒体文件,网页).
%ProgramFiles%,%ProgramFiles(x86)%
程序的默认安装位置.默认C:\Program Files和C:\Program Files (x86)
%CommonProgramFiles%
不知道干嘛的目录.默认C:\Program Files\Common Files
%SystemDrive%
操作系统盘符,默认C:
%SystemRoot%
操作系统文件目录,默认C:/windows
%windir%
在windows_NT操作系统中,是C:/windows
%ALLUSERSPROFILE%
所有用户的系统资源和配置的目录.默认C:/ProgramData,并且是隐藏的.
%USERDOMAIN%
用户所属工作组或windows域的名称
%USERPROFILE%
当前用户目录.如果你是Administrator,那就是C:\Users\Administrator
%PATHEXT%
在命令行通过%PATH%来查找可执行文件的时候可以加上这个变量的拓展名.java.exe只需要java就可以执行.
如果你增加一个.lnk的配置,通过命令行你可以直接打开快捷方式.其他文件同理.
%TEMP%,%TMP%
临时文件目录,包含一些缓存文件.这个目录实际上不是你在环境变量中看到的那个.
%CD%
当前目录
%TIME%
当前时钟时间,精确到0.01秒.
%DATE%
当前日期.
%RANDOM%
产生一个0到32767之间的随即数.
除了上面这些系统自身的环境变量,我们还需要定义一些程序运行时必须的环境变量,例如JAVA_HOME.
使用win+R来快速打开文件
在上面这么多环境变量中,最常用到的就是%PATH%.
win+R是windows提供的一个小工具,可以快速打开在%PATH%的路径列表下的所有可以打开的文件.
简单的用法演示:
我的google chrome的C:\Program Files (x86)\Google\Chrome\Application,如图:

为chrome.exe新建快捷方式并改名(简单短小的名字)

把他放到一个专门的快捷方式目录下,比如我放到了D:\shortcut\softsc
并且将这个目录配置到PATH中

确认之后通过win+R可以直接运行.

你可以快速打开所有应用程序的快捷方式或者文件夹或者你经常浏览的文件甚至网页的快捷方式.

三.JVM变量
jvm变量在运行时也有许多参数,并且System类会载入必要的属性到内部的Properties中.
通过以下这段简单的代码我们可以看到一个java程序从操作系统中载入的环境变量和以及系统属性.
import java.util.Map;
import java.util.Properties;/*** @author 无以铭川* @date 2019/8/9:上午 11:13*/
public class TestEnv {public static void main(String[] args) {Map<String, String> env = System.getenv();env.entrySet().forEach(System.out::println);Properties properties = System.getProperties();properties.entrySet().forEach(System.out::println);}
}

其中前部分大写字母的变量名都是环境变量,下面的则是系统属性.
通过命令行的-D参数我们可以增加一些变量,或者使用System.setProperty()来设定.
你可以通过设置一个JAVA_TOOL_OPTIONS环境变量来java.exe的运行参数.你所有的java程序都将使用JAVA_TOOL_OPTIONS中的参数来运行.

这段配置中不能出现中文,经过我的实测,大概是java.exe在加载命令行参数的时候使用的编码不是UTF-8,然后在实际运行中编码是UTF-8,这就会出现乱码.目前还没找到解决的办法.
jvm本身还有许多参数,不过那就是另一个话题了.
四.classpath
类路径,这在java程序中也是非常重要的一个环境属性,值是路径列表.java应用将会从路径列表中载入classpath中载入class文件.
回忆以下当初开始使用命令行来编译,运行java程序,多数人应该只是使用javac和java而没有加什么参数做了一遍HellWorld之后就进入了eclipse或者intellJ idea开发.
深究以下,IDE到底怎么帮助我们来编译,执行的?
先看看javac的参数.
-classpath <路径> 指定查找用户类文件和注释处理程序的位置
-cp <路径> 指定查找用户类文件和注释处理程序的位置
-sourcepath <路径> 指定查找输入源文件的位置
-d <目录> 指定放置生成的类文件的位置
-s <路径> 指定查找输入源文件的位置
我们可以自己来尝试使用一下.
新建目录如图,这与常见的maven构建的java应用结构类似.

两个类的信息:
package com.wymc.test;public class Test
{private String word;public void setWord(String word){this.word = word;}public String getWord(){return this.word;}
}
package com.wymc;
import com.wymc.test.*;public class TestMain
{public static void main(String[] args){Test test = new Test();test.setWord("hello world");String word = test.getWord();System.out.println(word);}
}
我们平常编写的代码正如上面所示.
然后使用javac编译之前,首先在src同级目录下新建一个classes文件夹,用于保存所有编译后的class文件.
mkdir classes
├───classes
└───src└───main└───java└───com└───wymc│ TestMain.java│└───testTest.java
然后进入java目录下执行下面的命令,因为java目录下才是我们的包开始的位置,其他目录会找不到类.
因为在这里默认使用到的classpath是.,当TestMain中import com.wymc.test.Test的时候,会到classpath下查找对应的类,但是只有在java目录下,才能找到正确的Test类的全路径.
cd src/main/java
javac -d ../../../classes com/wymc/**.java
这将把com/wymc下的这两个类都编译到classes目录.
tree /f
├───classes
│ └───com
│ └───wymc
│ │ TestMain.class
│ │
│ └───test
│ Test.class
│
└───src└───main└───java└───com└───wymc│ TestMain.java│└───testTest.java
执行TestMain
cd classes
java com.wymc.TestMain
当然我们也可以在src同级目录使用以下的命令编译.
javac -cp src/main/java/ -d classes src/main/java/com/wymc/**.java
这里使用-cp将src/main/java作为类路径,这样TestMain能够正确找到Test类所在的位置.
同样在执行的时候也可以指定classpath,jvm运行的时候将去这个目录下查找类并载入.
java -cp classes com.wymc.TestMain
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8 -Duser.name=wymc -Duser.timezone=GMT+8 -Dsun.jnu.encoding=UTF-8
hello world
显而易见的,jvm启动的时候会自动的将jdk中的类自动载入到运行环境中,而我们编写的类和第三方的类都需要通过classpath来引入,这样jvm才能够去找到类的位置.这也就是eclipse中的build path的作用,实质是通过将jar包的路径添加到了classpath中,一个常见的web应用的webapp目录下的lib目录则是默认的classpath路径,所以我们可以通过将jar放到这个目录就自动build path的效果.
那么,我们在开发过程中可能会碰到的找不到类的错误的原因也就可以根据上面的原理来总结出来:
-
同名类错误
java中一个类的全名实际上是包名+类名,环境中有不同包下的相同类并不是错误.这导致新人可能经常会犯一个错误,那就是定义一个与java.lang包下的类相同名的类.
尽管你可以新建这样一个类,而且不会报错,但是一旦你调用同名类的方法的时候就会出现问题.

如上就不会出现问题.这只是一种低级错误,相对来讲更加常见的是,你在项目A中定义了com.wymc.B,并且依赖了项目B,同时项目B中的有一个同样的类,com.wymc.B.这时候问题就发生了.你将有可能使用到的类不是你期望的那个.
-
依赖没有添加或者依赖错误
因为没有导入第三方jar包或者导入的版本错误而发生的找不到类的异常更为常见,也很容易解决.
在使用maven来构建项目的时候,也有可能发生这种错误,这可能是因为maven构建时没有指定classpath的问题.你可以使用mvn clean来删除并重新载入类路径.
另外使用maven时也有可能发生重复依赖的问题,这也会导致找不到正确的类,此时删除或者排除重复类的依赖就可以解决问题.
-
缓存未更新
IDE可能为文件添加缓存,有时候你重新编写的文件没有更新到缓存中,就可能导致环境中错误的类被载入.
eclipse中的tomcat可能有这样的问题,启动时发生找不到类的错误,即便删除其中部署的项目再重新部署,也依然有这样的错误,检查多次代码也没有问题.你尝试使用project->clean或者删除tomcat中部署的项目后先启动一次tomcat再重新部署你的项目.
-
错误的java版本
因为java版本而不能运行的错误比较少见且容易发现解决.
相对来说在IDE中的编译时错误更常见.比如intellJ idea中,有时候项目下新建maven模块的时候默认的java编译器等级是5,这将导致idea不能编译一些语法.
在classpath下可以配置一个环境变量,使用jdk自带的一些工具.
.;%JAVA_HOME%/jre/lib;%JAVA_HOME%/jre/lib/ext;%JAVA_HOME%/lib/tools.jar

tomcat中部署的项目后先启动一次tomcat再重新部署你的项目.
-
错误的java版本
因为java版本而不能运行的错误比较少见且容易发现解决.
相对来说在IDE中的编译时错误更常见.比如intellJ idea中,有时候项目下新建maven模块的时候默认的java编译器等级是5,这将导致idea不能编译一些语法.
在classpath下可以配置一个环境变量,使用jdk自带的一些工具.
.;%JAVA_HOME%/jre/lib;%JAVA_HOME%/jre/lib/ext;%JAVA_HOME%/lib/tools.jar
END
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
