天道酬勤,学无止境

Java 7u55 Eclipse 系统片段类加载器(Java 7u55 Eclipse System Fragment Classloader)

问题

在以前的 Java 版本中,我能够使用具有大量系统包的片段来为引导类加载器提供类。

在我的特殊情况下,这是为了支持在 Eclipse 中使用 Jacorb。 在 Java 7u55 之前,这一切都很好。

我创建了一个 osgi 片段,其中包含 Jacorb 的所有 jar。 清单如下所示:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: org.jacorb.systemFragment
Bundle-SymbolicName: org.jacorb.systemFragment
Bundle-Version: 3.3.0.20140422-1108
Bundle-ClassPath: jars/slf4j-jdk14-1.6.4.jar,
 jars/slf4j-api-1.6.4.jar,
 jars/jacorb-3.3.jar
Fragment-Host: system.bundle; extension:=framework
Export-Package: org.jacorb.config;version="3.3.0", ....

我还将以下内容指定为 vm args:

-Dorg.omg.CORBA.ORBClass=org.jacorb.orb.ORB
-Dorg.omg.CORBA.ORBSingletonClass=org.jacorb.orb.ORBSingleton
-Dorg.omg.PortableInterceptor.ORBInitializerClass.standard_init=org.jacorb.orb.standardInterceptors.IORInterceptorInitializer

当我在 Java 7u51 中运行我的 Eclipse 应用程序时,我能够成功调用 ORB.init()。

当我在 Java 7u55 中运行相同的应用程序时,我得到以下信息:

Caused by: java.lang.ClassNotFoundException: org.jacorb.orb.ORBSingleton
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:270)
at org.omg.CORBA.ORB.create_impl_with_systemclassloader(ORB.java:306)

如果我将以下内容添加为 vmargs,它将起作用。

 -Djava.endorsed.dirs=${jacorb/lib}

我确认这会影响 Java 7u55 Java 6u30 和 Java 8u5

我以前不需要这样做。 任何想法为什么?

--- 编辑 04/30 ---

做了更多的挖掘,我发现了导致问题的对 ORB.java 的提交。

changeset:   817:a8d27c3fc4e4
tag:         jdk7u55-b05
user:        msheppar
date:        Tue Jan 21 12:46:58 2014 +0000
summary:     8025005: Enhance CORBA initializations

这个提交改变了 ORB 类的创建方式。 现在硬编码使用 SystemClassLoader,而不是使用 Thread 上下文类加载器。

-                singleton = create_impl(className);
+                singleton = create_impl_with_systemclassloader(className);
         }
     }
     return singleton;
 }

+   private static ORB create_impl_with_systemclassloader(String className) {
+
+        try {
+            ReflectUtil.checkPackageAccess(className);
+            ClassLoader cl = ClassLoader.getSystemClassLoader();
+            Class<org.omg.CORBA.ORB> orbBaseClass = org.omg.CORBA.ORB.class;
+            Class<?> singletonOrbClass = Class.forName(className, true, cl).asSubclass(orbBaseClass);
+            return (ORB)singletonOrbClass.newInstance();
+        } catch (Throwable ex) {
+            SystemException systemException = new INITIALIZE(
+                "can't instantiate default ORB implementation " + className);
+            systemException.initCause(ex);
+            throw systemException;
+        }
+    }

我曾尝试将有关此问题的票记录到 Orcale。 同时,有没有办法通过某种片段覆盖 JVM 附带的 ORB.java?

回答1

我有同样的问题(我也看到很多其他人也有),但使用的是基于 CORBA 的 Webstart 应用程序。

此更改的问题在于,由于 u55 中的更改而被迫使用的 SystemClassLoader 不知道如何加载通过上述属性指定的 ORB 和 ORBSingleton 类,因为它们是应用程序类路径的一部分 - 就我而言由 JNLPClassloader 加载。

我想你的情况也有类似的情况。

通过指定-Djava.endorsed.dirs=${jacorb/lib/}来替换您已经使用的 orb.omg.CORBA 的 JDK 版本的一种方法。 这将 JDK 的 org.omg.CORBA 包版本替换为 JacORB 提供的包版本,JacORB 使用当前线程的 ContextClassLoader(与 u55 之前的代码所做的相同)。

另一种选择是使用例如-Xbootclasspath/p:${jacorb/lib/jar-containing-omg-api.jar}或将包含 JacORB 的 org.omg.CORBA 版本的 JAR 复制到<jre-home>/lib/endorsed .

不幸的是,这对我的 Webstart 应用程序问题没有帮助。

回答2

您是否需要系统范围/单例 ORB 才能成为 Jacorb ORB? 如果不是,那么这里最简单的解决方案可能是从命令行中删除 -Dorg.omg.CORBA.ORBSingletonClass。 请记住,单例 ORB 只是 TypeCode 工厂,您对 2-arg ORG.init 的调用仍将提供一个 Jacorb ORB,因为您已将 org.omg.CORBA.ORBClass 设置为选择它。

回答3

用户 3054250 提到的(最近更新,因为此信息之前没有)发行说明(谢谢您)指出了另一种可能的解决方法。 仅指定 ORB 属性但省略 ORBSingleton 在我的 CORBA/Webstart 应用程序中与 JacORB 3.4 一起工作(简短测试)。

它不适用于 OpenORB(因为 OpenORB 检查 ORBSingleton 的“正确”实例)所以我必须将我的应用程序升级到 JacORB,但它是一个解决方案。

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Java 7u55 Eclipse System Fragment Classloader
    In previous versions of Java I was able to use a fragment that had a host of system-bundle in order to provide classes to the boot classloader. In my particular case this was to support using Jacorb in Eclipse. This all worked fine prior to Java 7u55. I created an osgi fragment that contained all the jars for Jacorb. The manifest looks like this: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: org.jacorb.systemFragment Bundle-SymbolicName: org.jacorb.systemFragment Bundle-Version: 3.3.0.20140422-1108 Bundle-ClassPath: jars/slf4j-jdk14-1.6.4.jar, jars/slf4j-api-1.6.4.jar, jars
  • 无法更改组件属性值(Cannot Change Component Property Values)
    问题 我拥有最新版本的Redhawk和CentOS,并且马上遇到了一些问题。 最初我看不到“黑板”和“沙箱”,但是通过注释掉(#)eclipse.ini文件中的两行之一解决了该问题: -Dorg.omg.CORBA.ORBClass=org.jacorb.orb.ORB -Dorg.omg.CORBA.ORBSingletonClass=org.jacorb.orb.ORBSingleton 我从这里找到此修复程序。 应当指出,虽然没有出现明显的错误,但可能存在一些无法预料的问题。 我现在遇到的问题是,无法更改组件的属性值,例如频率或幅度。 我无法从属性视图或SCA组件编辑器中更改它们。 我尝试撤消#,但问题仍然存在。 从那以后,我一直在寻找JacORB的解决方案,因为“黑板”问题的根源似乎源于此。 这是错误日志中“ caused by”链中的最后一条: Caused by: java.lang.ClassNotFoundException: org.jacorb.orb.ORBSingleton at java.net.URLClassLoader$1.run(URLClassLoader.java:217) at java.security.AccessController.doPrivileged(Native Method) at java.net
  • 为什么Java 7中的StringBuilder#append(int)比Java 8中的快?(Why is StringBuilder#append(int) faster in Java 7 than in Java 8?)
    问题 在调查使用"" + n和Integer.toString(int)将整数基元转换为字符串的wrt时,我编写了以下JMH微基准测试: @Fork(1) @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) public class IntStr { protected int counter; @GenerateMicroBenchmark public String integerToString() { return Integer.toString(this.counter++); } @GenerateMicroBenchmark public String stringBuilder0() { return new StringBuilder().append(this.counter++).toString(); } @GenerateMicroBenchmark public String stringBuilder1() { return new StringBuilder().append("").append(this.counter++).toString(); } @GenerateMicroBenchmark public String stringBuilder2() {
  • 创建跨平台Java SWT应用程序(Create cross platform Java SWT Application)
    问题 我已经使用SWT编写了Java GUI。 我使用ANT脚本(下面的片段)打包了应用程序。 <jar destfile="./build/jars/swtgui.jar" filesetmanifest="mergewithoutmain"> <manifest> <attribute name="Main-Class" value="org.swtgui.MainGui" /> <attribute name="Class-Path" value="." /> </manifest> <fileset dir="./build/classes" includes="**/*.class" /> <zipfileset excludes="META-INF/*.SF" src="lib/org.eclipse.swt.win32.win32.x86_3.5.2.v3557f.jar" /> </jar> 这将产生一个jar,在Windows上,我只需双击即可运行我的GUI。 缺点是我不得不将Windows SWT程序包显式打包到我的jar中。 我希望能够在其他平台(主要是Linux和OS X)上运行我的应用程序。 最简单的方法是创建特定于平台的jar,将适当的SWT文件打包到单独的JAR中。 有一个更好的方法吗? 是否可以创建一个可以在多个平台上运行的JAR? 回答1
  • 通过getClass()。getResource()加载文件(File loading by getClass().getResource())
    问题 我遵循了通过使用getClass.getResource(path)加载资源文件的方法。 代码片段在这里: String url = "Test.properties"; System.out.println("Before printing paths.."); System.out.println("Path2: "+ getClass().getResource(url).getPath()); FileInputStream inputStream = new FileInputStream(new File(getClass().getResource(url).toURI())); i_propConfig.load(inputStream); inputStream.close(); 我已经在eclipse中使用层次结构对其进行了配置(在源代码下,有一个名为SwingDemo的文件夹。在SwingDemo中,有我的java文件以及资源文件)... src 摇摆演示 CustomDialog.java Test.properties 当我在Eclipse上运行时,一切运行正常。 但是,一旦我尝试从cmd行运行应用程序,则出现空指针异常。 命令行部署层次结构如下: 文件夹: D:\Work\Java Progrms\SwingDemo 等级制度: 摇摆演示
  • getResourceAsStream()返回null。 属性文件未加载(getResourceAsStream() is returning null. Properties file is not loading)
    问题 我正在尝试加载属性文件。 这是我的结构 现在,我正在尝试加载test.properties文件。 但我越来越空了。 这是我在做什么 public class Test { String workingDir = System.getProperty("user.dir"); System.out.println("Current working directory : " + workingDir); File temp = new File(workingDir + "\\" + "test.properties"); String absolutePath = temp.getAbsolutePath(); System.out.println("File path : " + absolutePath); Properties properties = null; try { properties = new Properties(); InputStream resourceAsStream = Test.class.getClassLoader().getResourceAsStream(absolutePath); if (resourceAsStream != null) { properties.load(resourceAsStream); } }
  • 取决于Eclipse中tools.jar(Sun JDK)中的com.sun.javadoc(Depending on com.sun.javadoc from tools.jar (Sun JDK) in Eclipse)
    问题 我们的插件之一需要已安装的JDK,而不仅仅是JRE。 我们需要com.sun.javadoc和来自tools.jar的朋友。 我认为Sun的许可证不会允许重新分发tools.jar(如果您已经拥有JDK,则没有必要)。 似乎在Eclipse中也没有办法将JDK指定为依赖项。 Eclipse新闻组中的所有答案都建议最终用户必须首先正确配置其Eclipse。 您是否知道有任何解决方法,仅通过使用Eclipse的机载机制来使依赖项对我们插件的用户显而易见? 与com.sun.jdi不同,此清单似乎对于清单中的Import-Package甚至无效。 (作为一种解决方法,当前我们只能在插件激活时警告该库丢失。) 回答1 由于eclipse提供了OSGi环境,因此您可以参考文章“在OSGi中公开启动类路径”,然后尝试使用: 系统软件包声明扩展捆绑(片段)声明或启动委派 通过指定所需的JDK软件包,OSGI框架将尝试加载它们(如果此处未包含,则会失败)。 通过指定特定于JDK5或JDK6的版本,您甚至可以确保JDK的正确版本。 OSGi规范允许框架(通过其系统捆绑包)使用org.osgi.framework.system.packages属性将其父类加载器中的所有相关软件包导出为系统软件包。 由于将托管JDK重新打包为捆绑包不是一个可行的选择,因此可以使用此设置让系统捆绑包
  • 模拟系统类时 Mockito + PowerMock LinkageError(Mockito + PowerMock LinkageError while mocking system class)
    问题 我有这样的代码片段: @RunWith(PowerMockRunner.class) @PrepareForTest({Thread.class}) public class AllMeasuresDataTest { @Before public void setUp() throws Exception { } @Test public void testGetMeasures() { AllMeasuresData measure = new AllMeasuresData(); assertEquals(measure.getMeasures(), null); HashMap<String, Measure> map = new HashMap<String, Measure>(); measure.setMeasures(map); assertEquals(measure.getMeasures(), map); measure.setMeasures(null); assertEquals(measure.getMeasures(), null); } @Test public void testAllMeasuresData() throws IOException { ClassLoader loader = PowerMockito.mock
  • 为什么自定义系统类加载器不起作用?(Why is custom system classloader not working?)
    问题 我正在尝试使用标志-Djava.system.class.loader=MyLoader覆盖系统的类加载器。 但是,加载类时仍未使用MyLoader 。 MyLoader的代码: public class MyLoader extends ClassLoader { public MyLoader(ClassLoader parent) { super(S(parent)); } private static ClassLoader S(ClassLoader cl) { System.out.println("---MyLoader--- inside #constructor(" + cl + ")..."); return cl; } @Override public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { System.out.println("---MyLoader--- inside loadClass(" + name + ", " + resolve + ")..."); return super.loadClass(name, resolve); } } 这是主要代码: public class Main { public static
  • CreateProcess错误= 206,运行main()方法时文件名或扩展名太长(CreateProcess error=206, The filename or extension is too long when running main() method)
    问题 我在日食日光灯中遇到此错误: 执行命令行时发生异常。 无法运行程序“ C:\ Program Files(x86)\ Java \ jre6 \ bin \ javaw.exe”(在目录“ C:\ Users \ motiver \ helios_workspace \ TimeTracker”中):CreateProcess错误= 206,文件名或扩展名是太长 我进行了一些研究,但大多数问题与使用Google App Engine时的DataNucleus有关。 但是我没有使用与Google App Engine远程相关的任何东西。 我正在JBOSS 6上使用Servlet 3.0做一个小项目。我正在使用Hibernate 4.1.2 for ORM和RESTEasy公开Web服务。 我创建了一个具有main()方法的util文件,该方法基本上删除并重新创建了架构。 当我需要一个干净的数据库进行测试时,我运行main()方法。 它在Tomcat 7上运行良好,但是在我移至JBoss 6时停止了工作。 任何提示或解决方案将不胜感激。 回答1 对于此问题,没有简单的解决方案(如单击几下或执行一个简单的命令)。 解决这些问题的方法是引用Eclipse.org中此错误报告中的一些答案。 选择最让您痛苦的一种: 减少类路径使用目录而不是jar文件使用包含所有其他jar的打包jar文件
  • 如何使用OSGi片段以相同的文件名贡献与平台相关的本机代码?(How to use OSGi fragments to contribute platform-dependent native code with the same filename?)
    问题 我正在使用JNotify项目来侦听文件系统事件。 这取决于每个OS:处理器体系结构的一个本机库。 例如,有一个针对Windows x86的库,一个针对x86-64的库,等等。 单片束 最初,我有一个捆绑包,其中包含JNotify Java类和本机代码。 本机代码在Bundle-NativeCode中声明如下: (我已将这些格式设置为bnd格式,以提高可读性……显然,正确形成了MANIFEST.MF文件)。 Bundle-NativeCode: jnotify_64bit.dll;osname=Win32;osname="Windows NT (unknown)";osname = WindowsXP;osname = Windows2000;osname = Windows2003;osname = WindowsVista;osname = Windows7;osname = WindowsServer2008;osname= Windows8;osname = WindowsServer2012;processor = x86-64,\ jnotify.dll;osname=Win32;osname="Windows NT (unknown)";osname = WindowsXP;osname = Windows2000;osname = Windows2003
  • 用于SupportMapFragment的findFragmentById在Android Studio中返回null(findFragmentById for SupportMapFragment returns null in Android Studio)
    问题 最近,我将一个项目从Eclipse迁移到了Android Studio。 除了我的一个使用SupportMapFragment的片段外,其他所有东西都已设置并正常运行。 下面的findFragmentById(在Eclipse中构建时有效)现在返回null :( public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); SupportMapFragment m = ((SupportMapFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.safety_map)); xml片段... <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:map="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" >
  • 如何枚举包中的所有类并将它们添加到列表中?(How can I enumerate all classes in a package and add them to a List?)
    问题 我需要枚举包中的所有类并将它们添加到列表中。 单个类的非动态版本如下所示: List allClasses = new ArrayList(); allClasses.add(String.class); 如何动态地在包及其所有子包中添加所有类? 更新:阅读了早期的答案后,我正在尝试解决另一个次要问题,这是绝对正确的,所以让我说一下。 我知道这是可能的,因为其他工具也可以做到。 在这里看到新问题。 更新:再次阅读此书,我可以了解它是怎么被误读的。 编译后,我希望从文件系统中枚举所有MY PROJECT'S类。 回答1 ****更新1(2012)**** 好的,我终于可以清理下面的代码片段了。 我将其粘贴到自己的github项目中,甚至添加了测试。 https://github.com/ddopson/java-class-enumerator ****更新2(2016)**** 有关更加健壮和功能丰富的类路径扫描器,请参见https://github.com/classgraph/classgraph。 我建议您先阅读我的代码片段以获得高水平的理解,然后再使用lukehutch的工具进行生产。 ****原帖(2010)**** 严格来说,不可能在package中列出这些类。 这是因为包实际上只不过是名称空间(例如com.epicapplications.foo.bar)
  • getClass()。getClassLoader()为null,为什么?(getClass().getClassLoader() is null, why?)
    问题 我有一些需要调用的代码。 x = getClass().getClassLoader(); 不过,这将返回null。 当我从命令行而不是从Eclipse启动相同的代码时,它将返回一个类加载器。 我可以破解代码来做到这一点... if (getClass().getClassLoader() == null) { x = ClassLoader.getSystemClassLoader().getSystemResourceAsStream( loadedPropFileName ); } 两者都被编译并使用相同的JVM运行。 (我确定99.99%)。 任何人都有任何想法,为什么第一个会为类加载器返回null? 编辑: 我的问题是:“没有人知道为什么同一类通过Eclipse启动时会返回null,而从命令行加载时会返回类加载器。” 感谢您提供的有关Bootstap加载程序必须在Eclipse中加载该类的建议。 我不知道为什么会这样。 回答1 引用API文档: 一些实现可能使用null来表示引导类加载器。 如果此类由引导类加载器加载,则在此类实现中此方法将返回null。 回答2 这就是它的工作方式。 每当JVM尝试加载任何类时,都会在以下条件下进行检查。 如果Class是从Bootstrap ClassPath加载的,即; jdk \ jre \ lib \ rt.jar
  • 使用 StringTemplate 代码生成器链接 Xtext(Linking Xtext with StringTemplate code generator)
    问题 在我当前的项目中,我试图链接用 xtext 编写的 DSL 规范和用 StringTemplate 编写的代码生成器。 例如,我的 DSL 规范的语法如下。 我正在通过 xText 提供的不错的编辑器工具输入这些信息。 structs: TempStruct tempValue : double; unitOfMeasurement : String; abilities : sensors: TemperatureSensor generate tempMeasurement : TempStruct; attribute responseFormat : String; 上述DSL规范的语法如下: VocSpec: 'structs' ':' (structs += Struct)+ 'abilities' ':' ('sensors' ':' (sensors += Sensor)+ )+ ; Sensor: name = ID ((attributes += Attributes ) | (sources += Sources))* ; Sources: 'generate' name=ID ':' type = Type ';' ; Attributes: 'attribute' name=ID ':' type = Type ';' ; Struct: name
  • 使用片段活动创建的ADT空白活动。(ADT blank activity created with fragment activity..)
    问题 我现在真的很困惑,因为每当我用空白活动创建一个新的android应用程序时,它总会带有fragment_main.xml。.我只是想创建一个没有空白活动的空白活动... 在第一张图片中,空白活动带有片段布局。 第二张图片显示了创建的fragment_main 现在我真的很困惑...这只是在将ADT更新到最新版本后才发生的(我已经提到了该线程):https://stackoverflow.com/questions/22203862/adt-doesnt-create-default-hello-world-但是-command-line-does#= 我只是想制作一个具有空白活动且没有片段视图的android应用... 回答1 对于那些想要有关如何从项目中删除片段的说明的人: 1)复制res / layout / fragment_main.xml的所有内容。 打开activity_main.xml,删除FrameLayout,然后粘贴复制的内容。 2)删除fragment_main.xml 3)在MainActivity.java中,删除整个PlaceHolderFragment类: /** * A placeholder fragment containing a simple view. */ public static class
  • 确定Java应用程序是否在Eclipse中处于调试模式(Determine if a java application is in debug mode in Eclipse)
    问题 我想更改日志记录级别,具体取决于是否在进行调试,但是找不到代码片段来检查应用程序是否在调试模式下运行。 我正在使用eclipse调试应用程序,因此,如果该解决方案仅在Eclipse中运行,那就可以了。 回答1 您可以修改调试配置。 例如,仅在“调试配置”中添加特殊的VM参数。 您可以使用System.getProperties()来读取提供的参数。 更好的是,修改配置(运行和调试)以加载不同的日志记录配置文件。 如果需要编写代码来确定日志记录级别,那就不好了。 这仅是配置问题。 回答2 找到了如何启用调试模式的答案 boolean isDebug = java.lang.management.ManagementFactory.getRuntimeMXBean(). getInputArguments().toString().indexOf("-agentlib:jdwp") > 0; 这将检查是否使用了Java调试线协议代理。 回答3 没有官方批准的方法可以从JVM内部可靠地确定任何给定的JVM是否处于调试模式,而依赖工件会在将来的某个时候破坏您的代码。 因此,您需要自己介绍一种方法。 意见建议: 系统属性。 环境变量(shell变量,例如$ HOME或%HOME%) 向JVM询问给定资源的物理位置-http://www.exampledepot.com/egs/java
  • Eclipse : java连接数据库MySQL超详细步骤
    Eclipse:java连接数据库MySQL 首先我们需要下载连接数据库所需要的桥JDBC。然后将其导入到项目中,其次编写连接数据库类。 下载MySQL JDBC 打开MySQL JDBC下载地址,然后根据自己电脑系统下载相对应的JDBC版本。如果是Windows,点击Go to Download Page去下载。下载完成之后解压得到mysql-connector-java文件夹。 导入JDBC 打开Eclipse,选中所需连接数据库的项目,右击——选中Build Path——选中Add External Archives…。 在弹窗中选中下载好的mysql-connector-java,然后点击打开,完成导入。 编写连接数据库(MySQL)类 创建一个连接数据库的类GetConnection。 package 连接数据库; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class GetConnection { public Connection getConn() { Connection con=null; //初始化Connection 对象 try { Class.forName("com.mysql.cj.jdbc
  • getResourceAsStream()与FileInputStream(getResourceAsStream() vs FileInputStream)
    问题 我试图在webapp中加载文件,并且在使用FileInputStream时遇到FileNotFound异常。 但是,使用相同的路径,当我执行getResourceAsStream()时,便能够加载文件。 两种方法有什么区别?为什么一种方法有效而另一种无效? 回答1 java.io.File和consorts作用于本地磁盘文件系统。 问题的根本原因是java.io中的相对路径取决于当前工作目录。 即从中启动JVM(在您的情况下为:Web服务器的目录)的目录。 例如,这可能是C:\Tomcat\bin或完全不同的东西,但不是C:\Tomcat\webapps\contextname或您希望的任何名称。 在普通的Eclipse项目中,它将是C:\Eclipse\workspace\projectname 。 您可以通过以下方式了解当前工作目录: System.out.println(new File(".").getAbsolutePath()); 但是,工作目录绝不是以编程方式可控制的。 您确实应该更喜欢在File API中使用绝对路径,而不是相对路径。 例如C:\full\path\to\file.ext 。 您不想硬编码或猜测Java(web)应用程序中的绝对路径。 那只是可移植性的麻烦(即它在系统X中运行,而不在系统Y中运行)。 通常的做法是将此类资源放置在类路径中
  • 什么加载Java系统类加载器?(What loads the java system classloader?)
    问题 我们知道我们可以使用以下方法覆盖System类加载器: java -Djava.system.class.loader=com.test.MyClassLoader xxx 然后,由于com.test.MyClassLoader本身是一个类,因此它是由谁加载的? 我们如何获得这个“元”类加载器的类文件? 回答1 从Javadoc中获取ClassLoader.getSystemClassLoader: 如果在首次调用此方法时定义了系统属性“ java.system.class.loader”,则该属性的值将作为要作为系统类加载器返回的类的名称。 该类使用默认的系统类加载器加载,并且必须定义一个公共构造函数,该构造函数采用单个类型为ClassLoader的参数作为委托父级。 默认的系统类加载器本身特定于JVM实现。 回答2 Bootstrap classloader是所有classloaders Bootstrap classloader的父级,并在JRE的lib目录(rt.jar和i18n.jar)中加载标准JDK类。 所有java。*类都由该classloader 。 Extensions Classloader是Bootstrap类加载器的直接子级。 该类加载器将类加载到JRE的lib \ ext目录中。 System-Classpath