InputStream is = getClass().getClassLoader().getResourceAsStream("helloworld.properties");
getClass()
:取得当前对象所属的Class对象
getClassLoader()
:取得该Class对象的类装载器
类装载器负责从Java字符文件将字符流读入内存,并构造Class类对象,所以通过它可以得到一个文件的输入流。
装载类的过程非常简单:查找类所在位置,并将找到的Java类的字节码装入内存,生成对应的Class对象。
Java的类装载器专门用来实现这样的过程,
JVM并不止有一个类装载器
,事实上,如果你愿意的话,你可以让JVM拥有无数个类装载器,当然这除了测试JVM外,我想不出还有其他的用途。
Class.getClassLoader()的一个小陷阱:
Integer.class.getClassLoader().getResource("*********");
抛出空指针异常,定位为getClassLoader()返回null
*
类装载器自身也是一个类,它也需要被装载到内存中来,*
那么这些类装载器由谁来装载呢?
它就是神龙见首不见尾的Bootstrap ClassLoader. 为什么说它神龙见首不见尾呢,因为你根本无法在Java代码中抓住哪怕是它的一点点的尾巴,尽管你能时时刻刻体会到它的存在,因为
java的运行环境所需要的所有类库,都由它来装载,
而它本身是C++写的程序,可以独立运行,
可以说是JVM的运行起点
。
在Bootstrap完成它的任务后,会生成一个AppClassLoader(实际上之前系统还会使用扩展类装载器ExtClassLoader,它用于装载Java运行环境扩展包中的类),这个类装载器才是我们经常使用的,可以调用ClassLoader.getSystemClassLoader() 来获得,我们假定程序中没有使用类装载器相关操作设定或者自定义新的类装载器,那么我们编写的所有java类通通会由它来装载,值得尊敬吧。AppClassLoader查找类的区域就是耳熟能详的Classpath,也是初学者必须跨过的门槛,有没有灵光一闪的感觉,我们按照它的类查找范围给它取名为类路径类装载器。还是先前假定的情况,当Java中出现新的类,AppClassLoader首先在类传递给它的父类类装载器,也就是Extion ClassLoader,询问它是否能够装载该类,如果能,那AppClassLoader就不干这活了,同样Extion ClassLoader在装载时,也会先问问它的父类装载器。我们可以看出类装载器实际上是一个树状的结构图,每个类装载器有自己的父亲,类装载器在装载类时,总是先让自己的父类装载器装载(多么尊敬长辈),如果父类装载器无法装载该类时,自己就会动手装载,如果它也装载不了,那么对不起,它会大喊一声:Exception,class not found。有必要提一句,当由直接使用类路径装载器装载类失败抛出的是NoClassDefFoundException异常。如果使用自定义的类装载器loadClass方法或者ClassLoader的findSystemClass方法装载类,如果你不去刻意改变,那么抛出的是ClassNotFoundException。
这里jdk告诉我们:如果一个类是通过bootstrap 载入的,那我们通过这个类去获得classloader的话,有些jdk的实现是会返回一个null的,比如说我用 new Object().getClass().getClassLoader()的话,会返回一个null,这样的话上面的代码就会出现NullPointer异常.所以保险起见最好还是使用\ 自己写的类来获取classloader(”this.getClass().getClassLoader()“),这样一来就不会有问题。
InputStream is = getClass().getClassLoader().getResourceAsStream("helloworld.properties");getClass():取得当前对象所属的Class对象getClassLoader():取得该Class对象的类装载器类装载器负责从Java字符文件将字符流读入内存,并构造Class类对象,所以通过它可以得到一
public static void main(String[] args) {
URL url = YamlUtil.
class
.get
ClassLoader
().getResource("");
System.out.println(url);
通过上面的结果,可以看到get
ClassLoader
().getResource()定位到项目的target/cla.
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
package org.apache.catalina.startup;
import
java
.io.File;
import
java
.io.IOException;
import
java
.lang.reflect.InvocationTargetException;
import
java
.lang.reflect.Method;
import
java
.net.MalformedURLException;
import
java
.net.URL;
import
java
.util.ArrayList;
import
java
.util.List;
import
java
.util.regex.Matcher;
import
java
.util.regex.Pattern;
import org.apache.catalina.Globals;
import org.apache.catalina.security.Security
Class
Load;
import org.apache.catalina.startup.
ClassLoader
Factory.Repository;
import org.apache.catalina.startup.
ClassLoader
Factory.RepositoryType;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
* Bootstrap loader for Catalina. This application constructs a
class
loader
* for use in loading the Catalina internal
class
es (by accumulating all of the
* JAR files found in the "server" directory under "catalina.home"), and
* starts the regular execution of the container. The purpose of this
* roundabout approach is to keep the Catalina internal
class
es (and any
* other
class
es they depend on, such as an XML parser) out of the system
*
class
path and therefore not visible to application level
class
es.
* @author Craig R. McClanahan
* @author Remy Maucherat
public final
class
Bootstrap {
private static final Log log = LogFactory.getLog(Bootstrap.
class
);
* Daemon object used by main.
private static Bootstrap daemon = null;
private static final File catalinaBaseFile;
private static final File catalinaHomeFile;
private static final Pattern PATH_PATTERN = Pattern.compile("(\".*?\")|(([^,])*)");
static {
// Will always be non-null
//System.getProperty("user.dir"),获取当前目录
//由于是在$CATALINA_HOME\bin下运行的Bootstrap,所以userDir为$CATALINA_HOME\bin
String userDir = System.getProperty("user.dir");
// Home first
//Globals是存放全局常量的类
//Globals.CATALINA_HOME_PROP = "catalina.home"
//catalina.home在运行Bootstrap时已设置(Tomcat的根目录)
String home = System.getProperty(Globals.CATALINA_HOME_PROP);
File homeFile = null;
//获取Tomcat的绝对路径
if (home != null) {
File f = new File(home);
try {
homeFile = f.getCanonicalFile();
} catch (IOException ioe) {
homeFile = f.getAbsoluteFile();
if (homeFile == null) {
// First fall-back. See if current directory is a bin directory
// in a normal Tomcat install
File bootstrapJar = new File(userDir, "bootstrap.jar");
if (bootstrapJar.exists()) {
File f = new File(userDir, "..");
try {
homeFile = f.getCanonicalFile();
} catch (IOException ioe) {
homeFile = f.getAbsoluteFile();
if (homeFile == null) {
// Second fall-back. Use current directory
File f = new File(userDir);
try {
homeFile = f.getCanonicalFile();
} catch (IOException ioe) {
homeFile = f.getAbsoluteFile();
//设置catalinaHomeFile
catalinaHomeFile = homeFile;
System.setProperty(
Globals.CATALINA_HOME_PROP, catalinaHomeFile.getPath());
// Then base
String base = System.getProperty(Globals.CATALINA_BASE_PROP);
//设置catalinaBaseFile
if (base == null) {
catalinaBaseFile = catalinaHomeFile;
} else {
File baseFile = new File(base);
try {
baseFile = baseFile.getCanonicalFile();
} catch (IOException ioe) {
baseFile = baseFile.getAbsoluteFile();
catalinaBaseFile = baseFile;
System.setProperty(
Globals.CATALINA_BASE_PROP, catalinaBaseFile.getPath());
// -------------------------------------------------------------- Variables
* Daemon reference.
private Object catalinaDaemon = null;
protected
ClassLoader
commonLoader = null;
protected
ClassLoader
catalinaLoader = null;
protected
ClassLoader
sharedLoader = null;
// -------------------------------------------------------- Private Methods
private void init
ClassLoader
s() {
try {
//创建commonLoader
commonLoader = create
ClassLoader
("common", null);
if( commonLoader == null ) {
// no config file, default to this loader - we might be in a 'single' env.
commonLoader=this.get
Class
().get
ClassLoader
();
//创建catalinaLoader、sharedLoader
catalinaLoader = create
ClassLoader
("server", commonLoader);
sharedLoader = create
ClassLoader
("shared", commonLoader);
} catch (Throwable t) {
handleThrowable(t);
log.error("
Class
loader creation threw exception", t);
System.exit(1);
private
ClassLoader
create
ClassLoader
(String name,
ClassLoader
parent)
throws Exception {
//CatalinaProperties解析$CATALINA_HOME\conf\catalina.properties,
//并将catalina.properties内的属性存为系统属性
//catalina.properties内common.loader="${catalina.base}/lib",
//"${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"
//读取common.loader
String value = CatalinaProperties.getProperty(name + ".loader");
if ((value == null) || (value.equals("")))
return parent;
//将${catalina.base},${catalina.home}替换为Tomcat的绝对路径
value = replace(value);
List<Repository> repositories = new ArrayList<>();
String[] repositoryPaths = getPaths(value);
for (String repository : repositoryPaths) {
// Check for a JAR URL repository
try {
@SuppressWarnings("unused")
URL url = new URL(repository);
repositories.add(
new Repository(repository, RepositoryType.URL));
continue;
} catch (MalformedURLException e) {
// Ignore
// Local repository
if (repository.endsWith("*.jar")) {
repository = repository.substring
(0, repository.length() - "*.jar".length());
repositories.add(
new Repository(repository, RepositoryType.GLOB));
} else if (repository.endsWith(".jar")) {
repositories.add(
new Repository(repository, RepositoryType.JAR));
} else {
repositories.add(
new Repository(repository, RepositoryType.DIR));
//
ClassLoader
Factory依据repositories的内容创建
ClassLoader
return
ClassLoader
Factory.create
ClassLoader
(repositories, parent);
* System property replacement in the given string.
* @param str The original string
* @return the modified string
protected String replace(String str) {
// Implementation is copied from
ClassLoader
LogManager.replace(),
// but added special processing for catalina.home and catalina.base.
String result = str;
int pos_start = str.indexOf("${");
if (pos_start >= 0) {
StringBuilder builder = new StringBuilder();
int pos_end = -1;
while (pos_start >= 0) {
builder.append(str, pos_end + 1, pos_start);
pos_end = str.indexOf('}', pos_start + 2);
if (pos_end < 0) {
pos_end = pos_start - 1;
break;
String propName = str.substring(pos_start + 2, pos_end);
String replacement;
if (propName.length() == 0) {
replacement = null;
} else if (Globals.CATALINA_HOME_PROP.equals(propName)) {
replacement = getCatalinaHome();
} else if (Globals.CATALINA_BASE_PROP.equals(propName)) {
replacement = getCatalinaBase();
} else {
replacement = System.getProperty(propName);
if (replacement != null) {
builder.append(replacement);
} else {
builder.append(str, pos_start, pos_end + 1);
pos_start = str.indexOf("${", pos_end + 1);
builder.append(str, pos_end + 1, str.length());
result = builder.toString();
return result;
* Initialize daemon.
public void init() throws Exception {
//创建commonLoader、catalinaLoader、sharedLoader
init
ClassLoader
s();
//为当前线程设置
ClassLoader
Thread.currentThread().setContext
ClassLoader
(catalinaLoader);
//设置Security
Class
Load。具体作用还不清楚。。。
Security
Class
Load.security
Class
Load(catalinaLoader);
// Load our startup
class
and call its process() method
if (log.isDebugEnabled())
log.debug("Loading startup
class
");
//通过反射实例化Catalina
Class
<?> startup
Class
=
catalinaLoader.load
Class
("org.apache.catalina.startup.Catalina");
Object startupInstance = startup
Class
.newInstance();
// Set the shared extensions
class
loader
if (log.isDebugEnabled())
log.debug("Setting startup
class
properties");
String methodName = "setParent
ClassLoader
";
Class
<?> paramTypes[] = new
Class
[1];
paramTypes[0] =
Class
.forName("
java
.lang.
ClassLoader
");
Object paramValues[] = new Object[1];
paramValues[0] = sharedLoader;
//通过反射设置Catalina的parent
ClassLoader
Method method =
startupInstance.get
Class
().getMethod(methodName, paramTypes);
method.invoke(startupInstance, paramValues);
//将实例化的Catalina赋值给catalinaDaemon
catalinaDaemon = startupInstance;
* Load daemon.
private void load(String[] arguments)
throws Exception {
// Call the load() method
//调用catalinaDaemon的load方法,并传递参数"start"
String methodName = "load";
Object param[];
Class
<?> paramTypes[];
if (arguments==null || arguments.length==0) {
paramTypes = null;
param = null;
} else {
paramTypes = new
Class
[1];
paramTypes[0] = arguments.get
Class
();
param = new Object[1];
param[0] = arguments;
Method method =
catalinaDaemon.get
Class
().getMethod(methodName, paramTypes);
if (log.isDebugEnabled())
log.debug("Calling startup
class
" + method);
method.invoke(catalinaDaemon, param);
* getServer() for configtest
private Object getServer() throws Exception {
String methodName = "getServer";
Method method =
catalinaDaemon.get
Class
().getMethod(methodName);
return method.invoke(catalinaDaemon);
// ----------------------------------------------------------- Main Program
* Load the Catalina daemon.
public void init(String[] arguments)
throws Exception {
init();
load(arguments);
* Start the Catalina daemon.
public void start()
throws Exception {
if( catalinaDaemon==null ) init();
//调用catalinaDaemon的start方法
Method method = catalinaDaemon.get
Class
().getMethod("start", (
Class
[] )null);
method.invoke(catalinaDaemon, (Object [])null);
* Stop the Catalina Daemon.
public void stop()
throws Exception {
Method method = catalinaDaemon.get
Class
().getMethod("stop", (
Class
[] ) null);
method.invoke(catalinaDaemon, (Object [] ) null);
* Stop the standalone server.
public void stopServer()
throws Exception {
Method method =
catalinaDaemon.get
Class
().getMethod("stopServer", (
Class
[]) null);
method.invoke(catalinaDaemon, (Object []) null);
* Stop the standalone server.
public void stopServer(String[] arguments)
throws Exception {
Object param[];
Class
<?> paramTypes[];
if (arguments==null || arguments.length==0) {
paramTypes = null;
param = null;
} else {
paramTypes = new
Class
[1];
paramTypes[0] = arguments.get
Class
();
param = new Object[1];
param[0] = arguments;
Method method =
catalinaDaemon.get
Class
().getMethod("stopServer", paramTypes);
method.invoke(catalinaDaemon, param);
* Set flag.
public void setAwait(boolean await)
throws Exception {
//通过反射,设置catalinaDaemon的await
Class
<?> paramTypes[] = new
Class
[1];
paramTypes[0] = Boolean.TYPE;
Object paramValues[] = new Object[1];
paramValues[0] = Boolean.valueOf(await);
Method method =
catalinaDaemon.get
Class
().getMethod("setAwait", paramTypes);
method.invoke(catalinaDaemon, paramValues);
public boolean getAwait()
throws Exception
Class
<?> paramTypes[] = new
Class
[0];
Object paramValues[] = new Object[0];
Method method =
catalinaDaemon.get
Class
().getMethod("getAwait", paramTypes);
Boolean b=(Boolean)method.invoke(catalinaDaemon, paramValues);
return b.booleanValue();
* Destroy the Catalina Daemon.
public void destroy() {
// FIXME
* Main method and entry point when starting Tomcat via the provided
* scripts.
* @param args Command line arguments to be processed
public static void main(String args[]) {
if (daemon == null) {
// Don't set daemon until init() has completed
//***2.1***
Bootstrap bootstrap = new Bootstrap();
try {
//***2.2***
bootstrap.init();
} catch (Throwable t) {
handleThrowable(t);
t.printStackTrace();
return;
//***2.3***
daemon = bootstrap;
} else {
// When running as a service the call to stop will be on a new
// thread so make sure the correct
class
loader is used to prevent
// a range of
class
not found exceptions.
Thread.currentThread().setContext
ClassLoader
(daemon.catalinaLoader);
//***2.4***
try {
String command = "start";
if (args.length > 0) {
command = args[args.length - 1];
if (command.equals("startd")) {
args[args.length - 1] = "start";
daemon.load(args);
daemon.start();
} else if (command.equals("stopd")) {
args[args.length - 1] = "stop";
daemon.stop();
} else if (command.equals("start")) {
//***2.5***
daemon.setAwait(true);
//***2.6***
daemon.load(args);
//***2.7***
daemon.start();
} else if (command.equals("stop")) {
daemon.stopServer(args);
} else if (command.equals("configtest")) {
daemon.load(args);
if (null==daemon.getServer()) {
System.exit(1);
System.exit(0);
} else {
log.warn("Bootstrap: command \"" + command + "\" does not exist.");
} catch (Throwable t) {
// Unwrap the Exception for clearer error reporting
if (t instanceof InvocationTargetException &&
t.getCause() != null) {
t = t.getCause();
handleThrowable(t);
t.printStackTrace();
System.exit(1);
* Obtain the name of configured home (binary) directory. Note that home and
* base may be the same (and are by default).
public static String getCatalinaHome() {
return catalinaHomeFile.getPath();
* Obtain the name of the configured base (instance) directory. Note that
* home and base may be the same (and are by default). If this is not set
* the value returned by {@link #getCatalinaHome()} will be used.
public static String getCatalinaBase() {
return catalinaBaseFile.getPath();
* Obtain the configured home (binary) directory. Note that home and
* base may be the same (and are by default).
public static File getCatalinaHomeFile() {
return catalinaHomeFile;
* Obtain the configured base (instance) directory. Note that
* home and base may be the same (and are by default). If this is not set
* the value returned by {@link #getCatalinaHomeFile()} will be used.
public static File getCatalinaBaseFile() {
return catalinaBaseFile;
// Copied from ExceptionUtils since that
class
is not visible during start
private static void handleThrowable(Throwable t) {
if (t instanceof ThreadDeath) {
throw (ThreadDeath) t;
if (t instanceof VirtualMachineError) {
throw (VirtualMachineError) t;
// All other instances of Throwable will be silently swallowed
// Protected for unit testing
protected static String[] getPaths(String value) {
List<String> result = new ArrayList<>();
Matcher matcher = PATH_PATTERN.matcher(value);
while (matcher.find()) {
String path = value.substring(matcher.start(), matcher.end());
path = path.trim();
if (path.startsWith("\"") && path.length() > 1) {
path = path.substring(1, path.length() - 1);
path = path.trim();
if (path.length() == 0) {
continue;
result.add(path);
return result.toArray(new String[result.size()]);
class
Gobang extends JFrame implements Runnable, ActionListener
final static int Player=1;
final static int AI =-1;
ClassLoader
cl = this.get
Class
().get
ClassLoader
();
Toolkit tk = Toolkit.getDefaultToolkit();
int length=14, game_state, winner, check, step;
int grid[][] = new int[length][length];
int locX, locY /* 囱竚 */, count /* 硈囱计 */, x, y /* 既竚 */, displace_x=0, displace_y=0 /* 簿秖 */, direction;
ArrayList steps = new ArrayList(); /* 癘魁囱˙ */
JPopupMenu control_menu = new JPopupMenu(); /* 龄匡虫 */
JMenuItem[] command = new JMenuItem[4];
String[] command_str={"囱", "郎", "弄郎", "秨"};
int[][] dir = { {-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1} };
boolean[] dir2 = new boolean[8];
boolean turn;
String message;
final JDialog dialog = new JDialog(this, "叫匡", true);
Font font=new Font("new_font", Font.BOLD, 20);
Grid grids[][] = new Grid[length][length];
Image white= tk.getImage(cl.getResource("res/white.png"));
Image black= tk.getImage(cl.getResource("res/black.png"));
Image title= tk.getImage(cl.getResource("res/title.png"));
Image temp;
JPanel boardPanel, bigpanel;
JRadioButton[] choice = new JRadioButton[2];
final static int Start =0;
final static int Select =1;
final static int Playing =2;
final static int End =3;
final static int nil=-1; /* 礚よ */
final static int oblique_1 =0; /* オ */
final static int oblique_2 =1; /* オ */
final static int horizontal =2; /* 绢 */
final static int vertical=3; /* */
Gobang()
super("き囱");
boardPanel = new JPanel();
boardPanel.setLayout(new GridLayout(length, length, 0, 0));
boardPanel.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
for(int i=0; i<length; i++)
for(int j=0; j<length; j++)
InputStream is = get
Class
().get
ClassLoader
().getResourceAsStream("helloworld.properties");
get
Class
():取得当前
对象
所属的
Class
对象
get
ClassLoader
():取得该
Class
对象
的类装载器
类装载器负责从
Java
字符文件将
字符流
读入
内存
,并构造
Class
类
对象
,所以通过它可以得到一个文件的输入流。
装载类的过程非常简单:查找类所在位置,并将找到的
Java
类的字节码装入
内存
,生成对应的Cl
InputStream is = get
Class
().get
ClassLoader
().getResourceAsStream("helloworld.properties");中get
Class
()和get
ClassLoader
()都是什么意思呀.
get
Class
():取得当前
对象
所属的
Class
对象
...
get
Class
().getResource()与get
ClassLoader
().getResource()的区别
文章目录get
Class
().getResource()与get
ClassLoader
().getResource()的区别简介测试结果Resources资源目录最终的问题总结
项目中我们经常要获取资源路径,我们会使用类名.get
Class
().getResource()和get
ClassLoader
().getResource()。这两个经常乱用,用着用着就迷了,
有些时候路径获取的
一文理解
class
.get
ClassLoader
().getResourceAsStream(file)和
class
.getResourceAsStream(file)区别
为什么是
class
path而不是src,因为当web项目运行时,IDE编译器会把src下的一些资源文件移至WEB-INF/
class
es,
class
Path目录其实就是这个
class
es目录。这个目录下放的一般是web项目运行时的
class
文件、资源文件(xml,properties...);
另外,在使用spring......
get
ClassLoader
()与get
Class
()的简单理解:
每一个
class
对象
都有一个get
ClassLoader
()方法,得到是谁把我从.
class
文件加载到
内存
中变成
Class
对象
的
而get
Class
()方法是获得调用该方法的
对象
的类
什么是类加载?
我们都知道,每个.
java
文件可以经过
java
c指令编译成.
class
文件,里面包含着
java
虚拟机的机器指令。当我们需要使用一个
java
类时,虚拟机会加载它的.
class
文件,创建对应的
java
对象
。将.
class
调入虚拟机的过程,称之为加载。
loading :加载。通过类的完全限定名找到.
class
字节码文件,同时创建一个
对象
。...
文章目录一、
ClassLoader
的作用二、
ClassLoader
层次结构三、
Class
加载时调用类加载器的顺序
一、
ClassLoader
的作用
我们都知道
java
程序写好以后是以.
java
(文本文件)的文件存在磁盘上,然后,我们通过(bin/
java
c.exe)编译命令把.
java
文件编译成.
class
文件(字节码文件),并存在磁盘上。
但是程序要运行,首先一定要把.
class
文件加载...
Tomcat启动时报: org.apache.catalina.core.AprLifecycleListener.init An incompatible version 错误
11626