在用户提交的代码中调用静态方法的更好方法是什么?

时间:2014-06-25 07:49:14

标签: java reflection

我有一个大数据集。我正在创建一个允许用户提交java源文件的系统,然后将其应用于数据集。更具体地说,每个提交的java源文件必须包含一个具有特定名称的静态方法,比如toBeInvoked()。 toBeInvoked将把一行数据集作为数组参数。我想在数据集的每一行上调用每个提交的源文件的toBeInvoked方法。我还需要实现安全措施(所以toBeInvoked()不能做I / O,不能调用exit等)。

目前,我的实现是这样的:我有一个java源文件名列表。对于每个文件,我创建了一个我编码的自定义安全ClassLoader的实例,它编译源文件并返回编译的类。我使用反射来提取静态方法toBeInvoked()(例如method = c.getMethod(“toBeInvoked”,double [] .class))。然后,我遍历数据集的行,并在每一行上调用该方法。

我的方法至少有两个问题:

  • 看起来很缓慢(我听说反射往往很慢)
  • 代码比我想要的更复杂

有没有更好的方法来完成我想要做的事情?

4 个答案:

答案 0 :(得分:0)

假设您的#toBeInvoked()可以在接口中定义而不是静态(它应该是!),您只需加载该类并将其强制转换为接口:

Class<? extends YourInterface> c = Class.forName("name", true, classLoader).asSubclass(YourInterface.class);
YourInterface i = c.newInstance();

然后直接调用#toBeInvoked()。

另请查看java.util.ServiceLoader,如果您有多个源文件,这可能有助于找到要加载的正确类。

答案 1 :(得分:0)

就个人而言,我会使用一个界面。这将允许您拥有多个具有自己状态的实例(对多线程很有用),但更重要的是,您可以使用接口,首先定义必须实现哪些方法,还要调用方法。

反射很慢,但这只与其他选项相关,例如直接方法调用。如果您正在扫描大型数据集,那么您必须从主内存中提取数据的事实可能要贵得多。

答案 2 :(得分:0)

鉴于您自己设定的限制,没有明显更好的方法。

对于它的价值,使这个“痛苦地慢”的原因是将源文件编译为类文件并加载它们。这比使用反射来调用方法要快许多个数量级。

(使用通用接口而不是静态方法不会对速度产生可测量的差异,并且复杂性的降低相对较小。)

如果您真的想要简化并加快速度,请更改您的体系结构,以便将代码作为包含所有已编译类的JAR文件提供。

答案 3 :(得分:0)

我建议您按照以下步骤解决问题。

  1. 要检查方法是否包含任何不需要的代码,您需要有一个检查脚本,可以在上传时执行这些检查。
  2. 创建一个具有toBeInvoked()方法的接口(不是静态方法)。
  3. 上传的所有类都必须实现此接口并在此方法中添加逻辑。
  4. 您可以让自定义类加载器扫描特定文件夹,以便添加新类并相应地加载它们。
  5. 上传文件并成功验证后,您可以将类文件编译并复制到类加载器扫描的文件夹中。
  6. 您的处理器类可以查找新文件,然后在需要时在加载的类上调用toBeInvoked()方法。
  7. 希望这有帮助。 (请注意,我使用了类似的机制来在开发的Workflow Engine工具中动态加载工作流步骤类。)