【发布时间】:2023-04-06 06:48:01
【问题描述】:
背景信息:
我有这个用于运行外部脚本的 java 框架。为此,我使用类加载器和系统 java 编译器的组合来编译我的项目构建路径中不存在的.java“脚本”文件。所有这些都有效,编译器黑魔法等等。
外部加载代码的固有复杂性是难以调试。我已经通过使用 java 运行时的远程调试功能解决了这个问题。
所以,我有一个附加到我的可执行 jar 的调试配置,它在源查找路径上有包含外部 java 脚本的目录。 这实际上工作了一段时间。实际上,它从来没有正常工作,我只是在构建路径上意外地有脚本。令人困惑的是,我可以在脚本中放置断点,而调试器实际上停止在那里(一致的行号,-verbose:class 日志记录等等)。 不过,了解 eclipse 如何找到源文件会有所帮助。毕竟,大部分 Eclipse 文档都包含用户手册。
我怀疑是我不小心复制了某些脚本文件,因此将源查找与不同步的源文件混淆了。事实并非如此,我已经删除了重复的文件,而 eclipse 仍然无法找到源代码。
我的尝试
- 双重、三重、四重检查源查找路径,确保它包含每个相关目录
- 启用/禁用搜索子文件夹
- 启用/禁用搜索重复项
- 使用目录的绝对路径而不是相对工作空间路径
解决方法
这里唯一的解决方法是将脚本文件添加到项目的构建路径中,这对我来说是不可接受的。
我现在在做什么
我正在通过 eclipse 开源项目基础存储库慢慢爬来寻找答案。事实证明,Eclipse 是一个相当大的项目。
问题
谁能提供 Eclipse 源代码查找工作原理的准确算法表示?
知道了这一点,我可能想出一种方法来强制 Eclipse 调试器使用反射来使用正确的路径。据我所知,没有任何技术限制阻止动态编译的代码被调试。我知道这一点是因为我的断点正在暂停我的线程,正如我所期望的那样,源代码似乎不想加载:(
相关研究:
似乎是this might be linked with how the class is defined with a null CodeSource location,但显然,在将代码动态编译到内存中时,正确的做法是给出 null arg...问题仍然是这对 eclipse 的调试器如何/为什么很重要。
更新 4/22 3:30:
所以我追求上面链接的CodeSource 解决方案。现在,我看到我的类正在使用-verbose:class 开关从正确的文件路径位置加载,但源查找仍然失败。断点仍然被正确捕获,但我看到了熟悉的Source not found 红色字体。
5/6 3:15 更新:
我追求安德鲁的回答中讨论的javap 解决方案。事实证明,我的 .class 字节码中的源文件属性与我的源查找路径中存在的文件完全匹配。这让我很困惑,因为这暗示文件夹层次结构对源查找有影响。但是,我创建了代表“真实”包(在我的 .java 文件顶部定义)的“幻像”包层次结构并将我的源文件移动到这些文件夹,但是当我将这些路径添加到时,源查找仍然失败我的源查找路径。任何关于源查找的额外因素的额外见解都将是巨大的。
【问题讨论】:
-
您是否收到任何错误消息?也许在错误日志视图或控制台视图中?您是否在调试窗口中通过右键单击编辑源查找 -> 在调试期间编辑源查找?
-
@calon 这是麻烦的一部分,Eclipse 除了“找不到源”之外什么也没说...不过,所有路径都在查找路径上。
-
用一些额外的研究更新了这个问题,但仍然没有走得太远
-
1) 您确定编译后的代码与源文件中的类名和包名匹配吗?编译器的技巧可能会重命名类。 2) 你确定 Eclipse 运行的是正确的类加载器吗?它可能认为源是与远程调试会话中的类同名的外来类。
-
@LorenzoGatti 我非常有信心类名匹配,我追求链接的
CodeSource可能的解决方案,现在我看到我的类文件(限定名称和所有)被声明为正在加载从我希望它被加载的位置。这是通过在我的重载getClassLoader()方法和getJavaFileForOutput()中编辑我的逻辑来实现的,在我的扩展ForwardingJavaFileManager<JavaFileManager>中支持为返回的classLoader 提供正确的CodeSource URL 位置。
标签: java eclipse debugging external