Java ClassLoader 类加载 与 SOA后期优化

2 篇文章 0 订阅
1 篇文章 0 订阅

Java ClassLoader 类加载 与 SOA后期优化

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

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

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

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 为例)的组成是:

  • 一些公共jar: spring-.jar , common-*.jar , db**jar,cache.jar 一般有个 大于 10M
  • 一些公共rpc jar : eg:dubbo**.jar 或其他的jar
  • 业务相关jar,class,resources
    这些jar都是要加载在内存里的啊;

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

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

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

到此结束!!!!
谢谢

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

question

  • 写在前面的话: 首先共享的前提是:大家都在运行在同一个进程里??
    一个tomcat 或其他web容器也是可以多实例运行.??

  • [x] 要共享的话 jar应该放在哪里?直接丢在jdk安装目录里的lib 行不行,为啥子( 不行!!)

  • [ ] 哪些是可以抽离去共享,大家都用的就可以共享吗

Java Class Loader简介


此处输入图片的描述


Bootstrp Class Loader 加载过的jar是:jre/lib,jre/classses

 /**
   * 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,这个世界那么多别人用过的对象…)。。。你自己统统搞定吧


此处输入图片的描述


ClassLoader.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 下 还是其他什么地方,看诸位的实验结果了…

(全是空口无凭)



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值