我是靠谱客的博主 冷艳银耳汤,最近开发中收集的这篇文章主要介绍Linux上关于Tomcat启动时与jdk环境变量设置的关系catalina.sh部分shell代码剪切问题: JDK里面的那些Tomcat用到的jar包由谁加载呢?不需要指定其具体位置吗?总结,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

catalina.sh部分shell代码剪切

		 shift
  touch "$CATALINA_OUT"
  if [ "$1" = "-security" ] ; then
    if [ $have_tty -eq 1 ]; then
      echo "Using Security Manager"
    fi
    shift
    eval $_NOHUP ""$_RUNJAVA"" ""$LOGGING_CONFIG"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS 
      -Djava.endorsed.dirs=""$JAVA_ENDORSED_DIRS"" -classpath ""$CLASSPATH"" 
      -Djava.security.manager 
      -Djava.security.policy==""$CATALINA_BASE/conf/catalina.policy"" 
      -Dcatalina.base=""$CATALINA_BASE"" 
      -Dcatalina.home=""$CATALINA_HOME"" 
      -Djava.io.tmpdir=""$CATALINA_TMPDIR"" 
      org.apache.catalina.startup.Bootstrap "$@" start 
      >> "$CATALINA_OUT" 2>&1 "&"

  else
    
    echo  "======================================================================================================"
    echo "打印启动详细的参数及路径 $_NOHUP  $_RUNJAVA $LOGGING_CONFIG $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS
      -Djava.endorsed.dirs=$JAVA_ENDORSED_DIRS -classpath $CLASSPATH
      -Dcatalina.base=$CATALINA_BASE
      -Dcatalina.home=$CATALINA_HOME
      -Djava.io.tmpdir=$CATALINA_TMPDIR
      org.apache.catalina.startup.Bootstrap $@ start"
    echo  "======================================================================================================"
    echo  "=============================================执行启动如下======================================="

    eval $_NOHUP ""$_RUNJAVA"" ""$LOGGING_CONFIG"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS 
      -Djava.endorsed.dirs=""$JAVA_ENDORSED_DIRS"" -classpath ""$CLASSPATH"" 
      -Dcatalina.base=""$CATALINA_BASE"" 
      -Dcatalina.home=""$CATALINA_HOME"" 
      -Djava.io.tmpdir=""$CATALINA_TMPDIR"" 
      org.apache.catalina.startup.Bootstrap "$@" start 
      >> "$CATALINA_OUT" 2>&1 "&"

  fi

  if [ ! -z "$CATALINA_PID" ]; then
    echo $! > "$CATALINA_PID"
  fi

  echo "Tomcat started."

elif [ "$1" = "stop" ] ; then

  shift

执行./startup.sh后控制台打印如下

======================================================================================================
打印启动详细的参数及路径   /usr/local/jdk1.7.0_79/bin/java -Djava.util.logging.config.file=/usr/local/apache-tomcat-7.0.70/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager  -Djdk.tls.ephemeralDHKeySize=2048  
      -Djava.endorsed.dirs=/usr/local/apache-tomcat-7.0.70/endorsed -classpath /usr/local/apache-tomcat-7.0.70/bin/bootstrap.jar:/usr/local/apache-tomcat-7.0.70/bin/tomcat-juli.jar 
      -Dcatalina.base=/usr/local/apache-tomcat-7.0.70
      -Dcatalina.home=/usr/local/apache-tomcat-7.0.70
      -Djava.io.tmpdir=/usr/local/apache-tomcat-7.0.70/temp
      org.apache.catalina.startup.Bootstrap  start
======================================================================================================
=============================================执行启动如下=======================================
Tomcat started.

从这里看出-classpath /usr/local/apache-tomcat-7.0.70/bin/bootstrap.jar:/usr/local/apache-tomcat-7.0.70/bin/tomcat-juli.jar是保证tomcat能被启动的基础,将一个含有主类的jar包加入类路径,同时在运行过程中依赖的类的jar包也添加进类路径

问题: JDK里面的那些Tomcat用到的jar包由谁加载呢?不需要指定其具体位置吗?

测试不同lib目录下jar包里面的类加载器及其父亲加载器

		 System.out.println(System.getProperty("user.dir"));
        ClassLoader t1 = Bootstrap.class.getClassLoader();
        System.out.println("Bootstrap classloader: " + t1);
        ClassLoader t2 = ZipFileAttributeView.class.getClassLoader();
        System.out.println("ZipFileAttributeView classloader: " + t2);
        ClassLoader t3 = String.class.getClassLoader();
        System.out.println("String classloader: " + t3);
        ClassLoader t4 = HashMap.class.getClassLoader();
        System.out.println("HashMap classloader: " + t4);

        ClassLoader t1Loader = t1.getClass().getClassLoader();
        System.out.println(t1 + "的classLoader: " + t1Loader);

        ClassLoader t2Loader = t2.getClass().getClassLoader();
        System.out.println(t2 + "的classLoader: " + t2Loader);

运行结果如下

	Bootstrap classloader           : sun.misc.Launcher$AppClassLoader@18b4aac2
    ZipFileAttributeView classloader: sun.misc.Launcher$ExtClassLoader@50675690
	String classloader              : null
	HashMap classloader             : null
	sun.misc.Launcher$AppClassLoader@18b4aac2的classLoader: null
	sun.misc.Launcher$ExtClassLoader@50675690的classLoader: null

值得一体的是他们分属的lib目录如下

类名lib目录类加载器类加载器的父亲
Bootstrapapache-tomcat-*binbootstrap.jarsun.misc.Launcher$AppClassLoadersun.misc.Launcher$ExtClassLoader
ZipFileAttributeViewjdkjrelibextzipfs.jarsun.misc.Launcher$ExtClassLoadernull
Stringjdkjrelibrt.jarnullnull
HashMapjdkjrelibrt.jarnullnull
	这里类加载为null的表示,该类的类加载器我们无法获取,它不是由Java实现的。jdkjrelib和 jdkjrelib|ext里面的jar包中的类分别由BootStrapClassLoader(非Java实现)和ExtClassLoader,而tomcat中bootstrap.jar包下的类是由AppClassLoader实现的

jdk jre中自带rt.jar包和jrelibext中的类,加载时,jvm会自动寻找,并且有不同的类加载去加载?验证代码如下

在这里插入图片描述
路径D:test 下面的, HelloWorld.java,只引用jdk自带的jdkjrelib和jdkjrelibext下面jar包中的类

	import sun.net.spi.nameservice.dns.DNSNameService;

	import java.util.HashMap;
	import java.util.Map;
	
	public class HelloWorld {
	
	    /**
	     * 引用String, jdkjrelibrt.jar中
	     */
	    public static void main(String[] args) throws Exception {
	        System.out.println("hello world");
	        Map<String, String> map = new HashMap<String, String>();
	        System.out.println(map.size());
	
	        // DNSNameService,jdkjrelibextdnsns.jar
	        DNSNameService t2 = new DNSNameService();
	
	        // 引用自定义的类
	//        Xiaomiing xiaomiing = new Xiaomiing("1205130232", "Jack");
	//        System.out.println(xiaomiing);
	    }
	}	

剔除本机环境下设置的CLASSPATH变量
在这里插入图片描述
检测是否剔除成功,如下图所示,是成功的
在这里插入图片描述
编译HelloWorld.java
在这里插入图片描述
有中文报错(对记住,命令行模式下,这里不能有中文),改成英文后,代码如下

	import sun.net.spi.nameservice.dns.DNSNameService;

	import java.util.HashMap;
	import java.util.Map;
	
	public class HelloWorld {
	
	    /**
	     * get reference form java.lang.String in jdkjrelibrt.jar
	     */
	    public static void main(String[] args) throws Exception {
	        System.out.println("hello world");
	        Map<String, String> map = new HashMap<String, String>();
	        System.out.println(map.size());
	
	        // DNSNameService,jdkjrelibextdnsns.jar
	        DNSNameService t2 = new DNSNameService();
	
	        // customized class
	//        Xiaomiing xiaomiing = new Xiaomiing("1205130232", "Jack");
	//        System.out.println(xiaomiing);
	    }
	}

再次编译,如下图,成功,但是我此时并没有指定要引用的这些jar包路径在哪,由此可见是jdk自己寻找的
在这里插入图片描述
在这里插入图片描述
运行代码,这个地方要注明自己编译的类所在的地方
在这里插入图片描述
将自定义的代码注释放开,源码如下

import partner.pals.Xiaomiing;
import sun.net.spi.nameservice.dns.DNSNameService;

import java.util.HashMap;
import java.util.Map;

public class HelloWorld {

    /**
     * get reference form java.lang.String in jdkjrelibrt.jar
     */
    public static void main(String[] args) throws Exception {
        System.out.println("hello world");
        Map<String, String> map = new HashMap<String, String>();
        System.out.println(map.size());

        // DNSNameService,jdkjrelibextdnsns.jar
        DNSNameService t2 = new DNSNameService();

        // customized class
        Xiaomiing xiaomiing = new Xiaomiing("1205130232", "Jack");
        System.out.println(xiaomiing);
    }
}

再次编译,如下图
在这里插入图片描述
这里可见自己定义的类似需要指明路径的,将编译后的自定义类拿到目录文件夹
在这里插入图片描述
在这里插入图片描述
再次编译,运行成功,如下图
在这里插入图片描述
如果换一种方式来编译,如下图,报错了,为什么
请注意:这里-classpath并不会为javac编译器提供任何引导作用,所以需要直接指明要编译的源文件的具体位置
请注意:这里-classpath并不会为javac编译器提供任何引导作用,所以需要直接指明要编译的源文件的具体位置

编译成功后,运行,如下
在这里插入图片描述
这里我们可以看到-classpath可以为java解释器提供类位置的引导作用

总结

	综上可知,得出如下结论:
	1.java jdk里面自带的jar包是由java运行时环境自动加载的,并且不同的lib目录下jar包里面的类由不同的类加载器加载,这里要提醒一下jrelib下		      的jar包并不是所有的都会被bootStrapClassLoader加载,但是jrelibext下的jar包确都会被Launcher$ExtClassLoader加载,比较幸运的是tomcat运行用到的jdk的jar包中的类都被bootStrapClassLoader和Launcher$ExtClassLoader加载了
	
	2.当编译一个java源文件时,引用到jdk里面自带的、 ‘被bootStrapClassLoader和Launcher$ExtClassLoader加载’的jar包的类时,无需将这些jar包添加到类路径中区,java虚拟机会自动去指定的地方寻找
	
	3.但是如果是用户自定义的类被该源文件引用,则需要将该自定义的类的根路径添加到类路径下面以辅助javac编译器来编译该源文件
	
	4.-classpath不会为javac编译器指明源文件的位置,因此我们需要将源文件的具体路径一并写上
	
	5.-classpath 会为java解释器提供引导作用,告诉java解释器,类的具体位置

	6.Tomcat相当于是一个指定的软件包,启动tomcat时,需要将其要使用的jar包添加到类路径

最后

以上就是冷艳银耳汤为你收集整理的Linux上关于Tomcat启动时与jdk环境变量设置的关系catalina.sh部分shell代码剪切问题: JDK里面的那些Tomcat用到的jar包由谁加载呢?不需要指定其具体位置吗?总结的全部内容,希望文章能够帮你解决Linux上关于Tomcat启动时与jdk环境变量设置的关系catalina.sh部分shell代码剪切问题: JDK里面的那些Tomcat用到的jar包由谁加载呢?不需要指定其具体位置吗?总结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(36)

评论列表共有 0 条评论

立即
投稿
返回
顶部