openFire 源码解读
2015-05-24 15:27
162 查看
1.openfire的入口main文件在src/java文件夹下的org.jivesoftware.openfire.starter包中。
2.运行main函数之后openfire会调用start方法,首先是获取到ClassLoader对象。那么什么是ClassLoader对象呢?
下面具体学习ClassLoader的知识。
首先ClassLoader作用是加载Class文件到jvm中,供程序使用,java程序可以动态加载类定义,这个动态加载的机制就是通过ClassLoader来实现的。
ClassLoader是加载Class文件的(ExtClassLoader和AppClassLoader也在此时被加载),那么ClassLoader又被谁加载呢?是一个被不是java语言所编写的ClassLoader来加载的,这个ClassLoader就是bootstrapClassLoader(启动类加载器)。这个加载器在jvm运行的时候加载java核心的api以满足java程序最基本的需求。其中包括用户定义的ClassLoader,用户定义的ClassLoader就是通过程序创建的ClassLoader,那么也有非程序员创建的ClassLoader,就是jvm自己提供的吧(这句是自己
理解的)。用户自定义的ClassLoader有ExtClassLoader,ExtClassLoader加载java的扩展的api,也就是/lib/ext中的类。用户自定义的ClassLoader还有AppClassLoader,AppClassLoader用户机器上的CLASSPATH设置目录中的Class的,通常在没有指定ClassLoader的情况下,程序自定义的类由AppClassLoader加载
ClassLoader的加载模式:双亲委托模式进行加载。该模式的原理是:某个自定义的ClassLoader加载Class的时候都会先委托他的parnetClassLoader加载该Class,当parentClassLoader加载失败,再由当前的ClassLoader加载该Class,但是如果该ClassLoader的parentClassLoader为null那么该ClassLoader的parent就是bootstrapClassLoader。
使用双亲委托模式的优点是:
第一:避免重复加载,当父亲已经加载了该类,那么子ClassLoader就没有必要加载该class了。
第二:安全因素。
3.获取当前类的类类加载器的方法:
[java]view
plaincopy
<spanstyle="background-color:rgb(51,153,102)">publicClassLoaderfindParentClassLoader(){
//获取父类加载器
ClassLoaderparent=Thread.currentThread().getContextClassLoader();
if(parent==null){
parent=this.getClass().getClassLoader();
if(parent==null){
parent=ClassLoader.getSystemClassLoader();
}
}
returnparent;
}</span>
4.类加载器的种类:
bootstrapclassLoader(引导类加载器)用来加载java的核心类库
extensionsclassloader(扩展类加载器)用来加载java的扩展库Java虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载Java类[ExtClassLoader]
系统类加载器(systemclassloader)Java应用的类都是由它来完成加载的。可以通过ClassLoader.getSystemClassLoader()来获取它[AppClassLoader]
上一节主要学习了jvm的类加载器,这节继续进行,从org.jivesoftware.openfire.starter.ServerStarter文件的第72行进行解读。
System.getProperty("openfire.lib.dir");
上面这句话是什么意思呢,根据字面意思理解应该是获取到当前项目也就是openfire的lib路径
继续往下读,如果存放lib的路径不存在那么就创建一个存放lib的文件夹
同样的通过这个方法可以获取到其他的属性如下列表
上一节我们阅读到了org.jivesoftware.openfire.starter.ServerStarter文件中的第90行,这节继续。
第90行调用unpackArchives(libDir,true);方法。
通过阅读该方法的英文注释大概意思是:转换文件夹中的一些包文件为一个标准的jar文件,在转换jar文件的同时每个被转的包文件就会被删除,如果包文件不存在,那么就什么都不做。
过滤文件
带着这句话我们进行阅读。该方法传入了2个参数,第一个是一个lib文件夹,第二个参数是个boolean值true。
[java]view
plaincopy
File[]packedFiles=libDir.listFiles(newFilenameFilter(){
publicbooleanaccept(Filedir,Stringname){
returnname.endsWith(".pack");
}
});
if(packedFiles==null){
//Donothingsinceno.packfileswerefound
return;
}
以上代码是unpackArchives方法中的146到155行的代码。
上面的第一句话我们大家应该很熟悉,没错,这句话我也经常用,但是我经常用不带参数的方法也就是一般这样用,
但是new接口的时候我们会发现我们就要实现里面所有的方法,少一个方法都不可以。因为
通过以上代码我们学习一个知识点,那就是获取某个文件夹下的某种格式的文件列表应该用
[java]view
plaincopy
File[]packedFiles=libDir.listFiles(newFilenameFilter(){
publicbooleanaccept(Filedir,Stringname){
returnname.endsWith(".pack");
}
});
如果没有获取到.pack类型的文件那么什么都不做,直接返回。
具体实现把.pack的文件转换为jar文件
上面我们获取到了.pack的文件数据,然后开始遍历该数组,把每个.pack文件转为jar文件。
关键代码如下
[java]view
plaincopy
<spanstyle="background-color:rgb(153,204,0)">InputStreamin=newBufferedInputStream(newFileInputStream(packedFile));
JarOutputStreamout=newJarOutputStream(newBufferedOutputStream(
newFileOutputStream(newFile(libDir,jarName))));
Pack200.Unpackerunpacker=Pack200.newUnpacker();
//Printsomethingsotheuserknowssomethingishappening.
if(printStatus){
System.out.print(".");
}
//Calltheunpacker
unpacker.unpack(in,out);
in.close();
out.close();
packedFile.delete();
unpacked=true;</span>
以上的
第三节中我们阅读了org.jivesoftware.openfire.starter.ServerStarter文件到91行,继续吧!
这节我们跳过108行之前的从108行开始学习,91行到107行相对比较简单。
从第108行到113行主要做了2件事情
第一:加载系统用到的jar包跟zip包到classpath中
第二:通过反射加载org.jivesoftware.openfire.XMPPServer类文件。
一:那么如何加载文件到classpath中呢
openfire用什么加载文件到classpath中:openfire中用org.jivesoftware.openfire.starter.JiveClassLoader加载文件到classpath中(该类是继承了URLClassLoader)
openfire加载文件到classpath的方法:
首先找出jar跟zip类型的文件,代码如下
然后调用父类URLClassLoader的addURL方法加载文件到classpath中,代码如下
二:如何通过反射加载文件?
到这里org.jivesoftware.openfire.starter.ServerStarter文件都阅读完毕,ServerStarter中主要做了如下几件事情:
获取classpath路径
把.pack文件转换为jar文件
获取当前线程的类加载器
创建自定义类加载器,并加载jar文件跟zip文件到classpath中
利用自定义的类加载器启动org.jivesoftware.openfire.XMPPServer类文件
2.运行main函数之后openfire会调用start方法,首先是获取到ClassLoader对象。那么什么是ClassLoader对象呢?
下面具体学习ClassLoader的知识。
首先ClassLoader作用是加载Class文件到jvm中,供程序使用,java程序可以动态加载类定义,这个动态加载的机制就是通过ClassLoader来实现的。
ClassLoader是加载Class文件的(ExtClassLoader和AppClassLoader也在此时被加载),那么ClassLoader又被谁加载呢?是一个被不是java语言所编写的ClassLoader来加载的,这个ClassLoader就是bootstrapClassLoader(启动类加载器)。这个加载器在jvm运行的时候加载java核心的api以满足java程序最基本的需求。其中包括用户定义的ClassLoader,用户定义的ClassLoader就是通过程序创建的ClassLoader,那么也有非程序员创建的ClassLoader,就是jvm自己提供的吧(这句是自己
理解的)。用户自定义的ClassLoader有ExtClassLoader,ExtClassLoader加载java的扩展的api,也就是/lib/ext中的类。用户自定义的ClassLoader还有AppClassLoader,AppClassLoader用户机器上的CLASSPATH设置目录中的Class的,通常在没有指定ClassLoader的情况下,程序自定义的类由AppClassLoader加载
ClassLoader的加载模式:双亲委托模式进行加载。该模式的原理是:某个自定义的ClassLoader加载Class的时候都会先委托他的parnetClassLoader加载该Class,当parentClassLoader加载失败,再由当前的ClassLoader加载该Class,但是如果该ClassLoader的parentClassLoader为null那么该ClassLoader的parent就是bootstrapClassLoader。
使用双亲委托模式的优点是:
第一:避免重复加载,当父亲已经加载了该类,那么子ClassLoader就没有必要加载该class了。
第二:安全因素。
3.获取当前类的类类加载器的方法:
[java]view
plain
<spanstyle="background-color:rgb(51,153,102)">publicClassLoaderfindParentClassLoader(){
//获取父类加载器
ClassLoaderparent=Thread.currentThread().getContextClassLoader();
if(parent==null){
parent=this.getClass().getClassLoader();
if(parent==null){
parent=ClassLoader.getSystemClassLoader();
}
}
returnparent;
}</span>
4.类加载器的种类:
bootstrapclassLoader(引导类加载器)用来加载java的核心类库
extensionsclassloader(扩展类加载器)用来加载java的扩展库Java虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载Java类[ExtClassLoader]
系统类加载器(systemclassloader)Java应用的类都是由它来完成加载的。可以通过ClassLoader.getSystemClassLoader()来获取它[AppClassLoader]
上一节主要学习了jvm的类加载器,这节继续进行,从org.jivesoftware.openfire.starter.ServerStarter文件的第72行进行解读。
System.getProperty("openfire.lib.dir");
上面这句话是什么意思呢,根据字面意思理解应该是获取到当前项目也就是openfire的lib路径
继续往下读,如果存放lib的路径不存在那么就创建一个存放lib的文件夹
同样的通过这个方法可以获取到其他的属性如下列表
java.version | Java运行时环境版本 |
java.vendor | Java运行时环境供应商 |
java.vendor.url | Java供应商的URL |
java.home | Java安装目录 |
java.vm.specification.version | Java虚拟机规范版本 |
java.vm.specification.vendor | Java虚拟机规范供应商 |
java.vm.specification.name | Java虚拟机规范名称 |
java.vm.version | Java虚拟机实现版本 |
java.vm.vendor | Java虚拟机实现供应商 |
java.vm.name | Java虚拟机实现名称 |
java.specification.version | Java运行时环境规范版本 |
java.specification.vendor | Java运行时环境规范供应商 |
java.specification.name | Java运行时环境规范名称 |
java.class.version | Java类格式版本号 |
java.class.path | Java类路径 |
java.library.path | 加载库时搜索的路径列表 |
java.io.tmpdir | 默认的临时文件路径 |
java.compiler | 要使用的JIT编译器的名称 |
java.ext.dirs | 一个或多个扩展目录的路径 |
os.name | 操作系统的名称 |
os.arch | 操作系统的架构 |
os.version | 操作系统的版本 |
file.separator | 文件分隔符(在UNIX系统中是“/”) |
path.separator | 路径分隔符(在UNIX系统中是“:”) |
line.separator | 行分隔符(在UNIX系统中是“/n”) |
user.name | 用户的账户名称 |
user.home | 用户的主目录 |
user.dir | 用户的当前工作目录 |
第90行调用unpackArchives(libDir,true);方法。
通过阅读该方法的英文注释大概意思是:转换文件夹中的一些包文件为一个标准的jar文件,在转换jar文件的同时每个被转的包文件就会被删除,如果包文件不存在,那么就什么都不做。
过滤文件
带着这句话我们进行阅读。该方法传入了2个参数,第一个是一个lib文件夹,第二个参数是个boolean值true。
[java]view
plain
File[]packedFiles=libDir.listFiles(newFilenameFilter(){
publicbooleanaccept(Filedir,Stringname){
returnname.endsWith(".pack");
}
});
if(packedFiles==null){
//Donothingsinceno.packfileswerefound
return;
}
以上代码是unpackArchives方法中的146到155行的代码。
上面的第一句话我们大家应该很熟悉,没错,这句话我也经常用,但是我经常用不带参数的方法也就是一般这样用,
File[]packedFiles=libDir.listFiles();
这样是获取到一个文件夹下的所有的文件。
而带参数的根据字面意思大概是过滤文件名称的意思,就是过滤一定规则的文件,而不是显示所有的文件,
过滤用
FilenameFilter这个接口,一般我们用接口都是通过继承的方法来使用,但是我们现在通过new的方式来使用,其实这种用法还是蛮多的,比如很多注册事件==很多地方都大量运用了该方法。
但是new接口的时候我们会发现我们就要实现里面所有的方法,少一个方法都不可以。因为
FilenameFilter接口只有一个方法
accept所以我们在new的同时就会实现该方法,我们通过该方法直接过滤以某种后缀名的文件就可以了现在我们要列出.pack类型的文件所以我们应该写
return
name.endsWith(
".pack"
);就可以获取到了。很方便吧。
通过以上代码我们学习一个知识点,那就是获取某个文件夹下的某种格式的文件列表应该用
FilenameFilter来实现,实现方法是一下代码
[java]view
plain
File[]packedFiles=libDir.listFiles(newFilenameFilter(){
publicbooleanaccept(Filedir,Stringname){
returnname.endsWith(".pack");
}
});
如果没有获取到.pack类型的文件那么什么都不做,直接返回。
具体实现把.pack的文件转换为jar文件
上面我们获取到了.pack的文件数据,然后开始遍历该数组,把每个.pack文件转为jar文件。
关键代码如下
[java]view
plain
<spanstyle="background-color:rgb(153,204,0)">InputStreamin=newBufferedInputStream(newFileInputStream(packedFile));
JarOutputStreamout=newJarOutputStream(newBufferedOutputStream(
newFileOutputStream(newFile(libDir,jarName))));
Pack200.Unpackerunpacker=Pack200.newUnpacker();
//Printsomethingsotheuserknowssomethingishappening.
if(printStatus){
System.out.print(".");
}
//Calltheunpacker
unpacker.unpack(in,out);
in.close();
out.close();
packedFile.delete();
unpacked=true;</span>
以上的
packedFile是遍历每个.pack的文件。就这样把.pack文件转为了jar文件。
第三节中我们阅读了org.jivesoftware.openfire.starter.ServerStarter文件到91行,继续吧!
这节我们跳过108行之前的从108行开始学习,91行到107行相对比较简单。
从第108行到113行主要做了2件事情
第一:加载系统用到的jar包跟zip包到classpath中
第二:通过反射加载org.jivesoftware.openfire.XMPPServer类文件。
一:那么如何加载文件到classpath中呢
openfire用什么加载文件到classpath中:openfire中用org.jivesoftware.openfire.starter.JiveClassLoader加载文件到classpath中(该类是继承了URLClassLoader)
openfire加载文件到classpath的方法:
首先找出jar跟zip类型的文件,代码如下
获取classpath路径
把.pack文件转换为jar文件
获取当前线程的类加载器
创建自定义类加载器,并加载jar文件跟zip文件到classpath中
利用自定义的类加载器启动org.jivesoftware.openfire.XMPPServer类文件
相关文章推荐
- openfire源码解读之将cache和session对象移入redis以提升性能
- openFire 源码解读
- openfire源码解读之将cache和session对象移入redis以提升性能
- openfire源码解读-用户登录
- JDK之CopyOnWriteArrayList源码解读
- spring IOC源码解读
- JVM源码分析之javaagent原理完全解读
- JDK8之HashMap源码解读
- jieba分词源码解读一
- cakephp 2.0 源码解读(一)
- ArrayList源码简略解读
- 基于Docker的TensorFlow机器学习框架搭建和实例源码解读
- (版本定制)第14课:Spark Streaming源码解读之State管理之updateStateByKey和mapWithState解密
- java源码解读之LinkedHashMap------jdk 1.7
- gnu coreutils4.5.1 logname.c源码解读
- Spring AOP源码解读2 - 切面和增强的取得
- AFNetworking 3.0 源码解读(九)之 AFNetworkActivityIndicatorManager
- Android IntentService源码解读
- 第10课:Spark Streaming源码解读之流数据不断接收全生命周期彻底研究和思考
- openlayers4源码解读系列