Java ClassLoader 类加载 与 SOA 后期优化

2015-12-15 19:50:09 +08:00
 tianzhidao28

Java ClassLoader 类加载 与 SOA 后期优化

标签(空格分隔): jetty soa application

现在见到的一些应用部署方式(我见到的)

只能说是我见到的这 2 种
- 1 . mvn clean package 打成 war 再丢到 web 容器
- 2 . mvn clean package 打成 jar 直接运行(这是我这一年才见到的这么粗暴的方式),但也简单干脆,
最近看 jetty 官网也逐渐感觉或许这是个不错的单应用选择吧

Don't deploy your application in Jetty, deploy Jetty in your application!

use jetty as a http module,not a web container
just a module of your application


在一个大的系统砸碎成一片片的服务的后期,就会产生一大波妹子了, 不 , 一大波的服务 s,
一般一个服务(以 java 为例)的组成是:

10 个就重复 10 遍 9 * 10M(?)内存的浪费

当然在 内存也就那点钱,摩尔定律 完全可以解决这个问题,

能用钱解决的问题更本就不是问题

到此结束!!!!
谢谢

朴素的劳动人民的品格教育我们,贪污浪费都是犯罪.
同时也见到有朋友公司有把公共的一部分 jar 抽离放在容器里共享的先例。

question

Java Class Loader 简介

Bootstrp Class Loader 加载过的 jar 是: jre/lib,jre/classses
```java
/**
* bootstrap 加载的核心内裤
*/
URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (int i = 0; i < urls.length; i++) {
System.out.println(urls[i].toExternalForm());
}

file:/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/jre/lib/resources.jar
file:/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/jre/lib/rt.jar
file:/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/jre/lib/sunrsasign.jar
file:/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/jre/lib/jsse.jar
file:/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/jre/lib/jce.jar
file:/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/jre/lib/charsets.jar
file:/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/jre/lib/jfr.jar
file:/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/jre/classes

`ExtClassLoader : ` 加载的是 jre\lib\ext 目录或者,参数 java.ext.dirs 指定的目录

`AppClassLoader :` 加载 classpath 指定的目录 ,我们自己写的 Java 文件一般默认就是这货加载的,

`XXXXClassLoader : `自己定义加载类的 classloader------>parent = AppCLassLoader

### 类加载机制 
> 向上委托,全部丢给你老大,你老大再丢给他的老大,当老大搞定不了了,就交给他小弟喽。。。直到你的直接领导也搞不定 就交给你去搞
> 全盘负责, 一旦某个 classLoader 决定加载一个类的时候,这个类用过的对象的那些类也由这个 ClassLoader 负责了..你用过的对象,别人怎么用(™D,这个世界那么多别人用过的对象...)。。。你自己统统搞定吧

![此处输入图片的描述][3]

ClassLoader.java
```java

@CallerSensitive
public final ClassLoader getParent() {
        if (parent == null)
            return null;
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkClassLoaderPermission(parent, Reflection.getCallerClass());
        }
        return parent;
}

 protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            // 检查是否被加载过
            Class c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        // go daddy 丢给你爸爸去加载,递归下去 找你爷爷,....
                        c = parent.loadClass(name, false);
                    } else {
                        // ExtClassLoader 的 
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }

随手写了一段验证下 自定义的 ClassLoader;得到的 父 ClassLoader 是 ExtClassLoader ....
```
FileSystemClassLoader fileSystemClassLoader = new FileSystemClassLoader("/");

System.out.println("classpath: " + fileSystemClassLoader.getParent().toString());

凭什么啊! 从代码上也没看出指定父 ClassLoader 的地方,我艹
后留意到 
`@CallerSensitive`
public final ClassLoader getParent() 

这个鬼注解,
从 Oracle 官网找了一段话 依然没怎么看懂,,(有了解少少或看到相关人能看懂的说明,@我)

Guideline 9-9 / ACCESS-9: Safely invoke standard APIs that perform tasks using the immediate caller's class loader instance
The following static methods perform tasks using the immediate caller's class loader:

java.lang.Class.forName
    java.lang.Package.getPackage(s)
    java.lang.Runtime.load
    java.lang.Runtime.loadLibrary
    java.lang.System.load
    java.lang.System.loadLibrary
    java.sql.DriverManager.deregisterDriver     
    java.sql.DriverManager.getConnection
    java.sql.DriverManager.getDriver(s)
    java.util.logging.Logger.getAnonymousLogger
    java.util.logging.Logger.getLogger
    java.util.ResourceBundle.getBundle

Methods such as these that vary their behavior according to the immediate caller's class are considered to be caller-sensitive, and should be annotated in code with the @CallerSensitive annotation [16].

For example, System.loadLibrary("/com/foo/MyLib.so") uses the immediate caller's class loader to find and load the specified library. (Loading libraries enables a caller to make native method invocations.) Do not invoke this method on behalf of untrusted code, since untrusted code may not have the ability to load the same library using its own class loader instance. Do not invoke any of these methods using inputs provided by untrusted code, and do not propagate objects that are returned by these methods back to untrusted code.

不纠结这个鬼了。

### Jetty Web 容器的 ClassLoader : 
每个 web 上下文( web 应用和 war 文件)的普通配置是有自身的 classloader ,系统的 classloader 是它的父类。这是普通的 java classloader 的层次,但是 servlet 规范提出了负责的层次要求:

1. 在 WEB-INF/lib 和 WEB-INF/classes 中包含的类的加载优先级高于父 classloader 中的类。这和普通的 java2 的 classloader 加载动作相反。

2. 像 java.lang.String 这样的系统类不会被 WEB-INF/lib 或者 WEB-INF/classes 中的类替代。不幸的是, servlet 规范并没有清楚的规定哪些类是系统类,也没有清楚的指出 javax 类应该作为系统类

3. Server 实现类应该对 web 应用和其他 classloader 不可见。不幸的是, servelt 规范并没有规定什么是 server class ,也没有清楚的指出像 xerces parser 这样的 common libraries 应该作为实现类。


具体的哪些 jar 放在 jetty.home/XXX/lib 下 还是其他什么地方,看诸位的实验结果了...

`(全是空口无凭)`
---
![qrcoe][4]
2476 次点击
所在节点    Java
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/243773

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX