Java 当前运行的类或JAR文件的位置

Java 当前运行的类或JAR文件的位置,java,jar,lotus-notes,Java,Jar,Lotus Notes,我有一个数据库,它正在执行与远程web服务的一些交互。我已经编写了一个自定义Java类来执行交互 根据用户的设置,可以从三个位置之一执行类方法: 在通过LotusNotesJava代理调用的Java脚本库中 在位于用户“jvm/lib/ext”目录中的JAR文件中 在位于用户“jvm/lib”目录(例如,“jvm/lib/custom_dir”)的自定义目录中的JAR文件中。LotusNotesJVM通过使用“JavaUserClassesExt”本地Notes.ini变量了解自定义目录 在我的

我有一个数据库,它正在执行与远程web服务的一些交互。我已经编写了一个自定义Java类来执行交互

根据用户的设置,可以从三个位置之一执行类方法:

  • 在通过LotusNotesJava代理调用的Java脚本库中
  • 在位于用户“jvm/lib/ext”目录中的JAR文件中
  • 在位于用户“jvm/lib”目录(例如,“jvm/lib/custom_dir”)的自定义目录中的JAR文件中。LotusNotesJVM通过使用“JavaUserClassesExt”本地Notes.ini变量了解自定义目录
  • 在我的类中,我只希望能够返回当前类执行的位置。因此,如果它是从选项2或选项3执行的,则返回JAR文件路径。如果它是从选项1执行的,那么返回我可以处理的其他内容

    我试过以下方法

    //Normally you don't ever want to do this......
    Class clazz = ClassLoader.class;
    Field field = clazz.getDeclaredField("sys_paths");
    field.setAccessible(true);
    field.setClass(clazz, null);
    try {
         //Basically we read in the path and then loop through and remove our current
         //directory which is where we tend to "kick off from" rather than where we want
         //to run from.
         String minusCurrentDir = removeCurrentDirectoryFromPath(System.getProperty("java.library.path");
         System.setProperty("java.library.path", minusCurrentDir);
    }
    finally {
         field.setAccessible(true);
    }
    
    getProtectionDomain()方法 其结果是:

    java.security.AccessControlException: Access denied (java.lang.RuntimePermission getProtectionDomain)
    
    没有任何选项可以更改运行此操作的任何客户端上的任何安全设置

    Class.getResource方法 结果:myResourceURL始终为空

    ClassLoader.getResource方法 结果:myResourceURL2始终为空

    a) 我在上面哪里出错了


    b) 如何使用其他方法获取当前正在执行的类的位置?

    您的最后一行代码是
    myCL.getresource(myName)
    ,应该使用
    myName2
    。这可能会引起问题。如果它使用的名称版本带有前导“/”,那么您将无法从ClassLoader.getResource()调用中获得任何信息。它必须没有前导斜杠。如果没有帮助,您也可以尝试:

    ClassLoader.getSystemResource(myName2); // name without leading slash
    

    如果这仍然不起作用,那可能是一个安全问题。根据,如果“调用者没有足够的权限获取资源”,它可以返回null。我只知道Java,不知道Lotus,所以我不知道它在什么样的安全环境中运行代码。

    我通过将代码包装在“AccessController.doPrivileged”块中,成功地克服了这一问题,即:

    final String[] myLocationViaProtectionDomain = {null};
    AccessController.doPrivileged(new PrivilegedAction(){
        public Object run(){
            myLocationViaProtectionDomain[0] = getClass().getProtectionDomain().getCodeSource().getLocation().toString();
            debug("myLocationViaProtectionDomain: " + myLocationViaProtectionDomain[0]);
            return null;
        }
    });
    
    有趣的是,当JAR文件位于客户机的JVM目录中时,即我最初文章中的第2点和第3点时,这种方法正是我想要的。但是,当从Java脚本库中执行代码时运行相同的代码时,会引发以下异常:

    java.security.AccessControlException: Access denied (java.lang.RuntimePermission getProtectionDomain)
    
    这很好,因为至少在1和(2&3)之间有一个区别,我可以正确处理


    lekkimworld.com(Twitter:@lekkim)优秀的Mikkel向我指出了这个解决方案,非常感谢他。

    我不确定这是否有帮助,但我们“切换”了
    user.dir(系统属性),以确保应用程序的某个目录“用完”。在我们的例子中,我们有一个通过LotusNotes启动的web start应用程序(它调用一个BAT文件,调用(JAWS)…)

    但无论如何,我们要做的是以下几点

    //Normally you don't ever want to do this......
    Class clazz = ClassLoader.class;
    Field field = clazz.getDeclaredField("sys_paths");
    field.setAccessible(true);
    field.setClass(clazz, null);
    try {
         //Basically we read in the path and then loop through and remove our current
         //directory which is where we tend to "kick off from" rather than where we want
         //to run from.
         String minusCurrentDir = removeCurrentDirectoryFromPath(System.getProperty("java.library.path");
         System.setProperty("java.library.path", minusCurrentDir);
    }
    finally {
         field.setAccessible(true);
    }
    

    现在,您可以访问和修改
    user.dir
    属性,或者询问它在哪里。这可能会让您访问您想要的内容(?),或者至少顶部代码可能会有所帮助。

    谢谢您的评论,Ryan,很好。myName vs myName2的使用只是我原始描述中的一个输入错误,即使用正确的变量名而不使用前面的斜杠时,我得到了相同的行为。感谢您的回答,Chris,但我通过将代码包装在
    AccessController.doPrivileged
    调用中,成功地获得了所需的内容。详情请参见下面我的答案。您可能应该将其标记为您问题的答案。它帮助别人知道你需要做什么。谢谢你的提醒。对StackOverflow来说还是个新手,所以不知道什么是适当的礼仪。我已经标出了答案,以后会记住的!
    java.security.AccessControlException: Access denied (java.lang.RuntimePermission getProtectionDomain)
    
    //Normally you don't ever want to do this......
    Class clazz = ClassLoader.class;
    Field field = clazz.getDeclaredField("sys_paths");
    field.setAccessible(true);
    field.setClass(clazz, null);
    try {
         //Basically we read in the path and then loop through and remove our current
         //directory which is where we tend to "kick off from" rather than where we want
         //to run from.
         String minusCurrentDir = removeCurrentDirectoryFromPath(System.getProperty("java.library.path");
         System.setProperty("java.library.path", minusCurrentDir);
    }
    finally {
         field.setAccessible(true);
    }