标签: groovyclassloader

从gradle中运行groovy脚本

创建一个运行groovy脚本的gradle任务的最佳方法是什么?我意识到gradle构建文件是常规的,所以我认为可以做这样的事情:

task run << {
    Script app = new GroovyShell().parse(new File("examples/foo.groovy"))
    // or replace .parse() w/ a .evalulate()?
    app.run()
}
Run Code Online (Sandbox Code Playgroud)

如果bar.groovy正在使用@Grab注释甚至是简单的导入,那么当我尝试这个时,我会遇到各种各样的错误.我想创建一个任务的Gradle来处理这个问题,让我能有希望重用的类路径定义.

examples目录移动到某个地方的src目录会更好吗?什么是最佳做法?

groovy gradle groovyclassloader

18
推荐指数
3
解决办法
6398
查看次数

GroovyClassLoader调用parseClass成功,即使代码未编译也是如此

我正在尝试将Groovy脚本作为类动态加载,但是即使脚本的代码无法编译,也会创建类对象。

例如,用于加载Groovy脚本的我的Groovy代码的简化版本如下:

GroovyCodeSource src = new GroovyCodeSource(
    "blah blah blah",
    "Foo.groovy",
    GroovyShell.DEFAULT_CODE_BASE
)
new GroovyClassLoader().parseClass(src, true)
Run Code Online (Sandbox Code Playgroud)

显然,该代码blah blah blah不是合法的Groovy脚本。但是,已经为该动态代码成功创建了一个类对象。根据GroovyClassLoader的Javadoc,对于这种parseClassCompilationFailedException情况,应抛出方法 a 。

如何仍然为残破的代码创建类,以及如何根据条件是否编译将如何从动态Groovy源代码成功创建类?我做了很多研究和实验,但无济于事。

java groovy classloader groovyclassloader

6
推荐指数
1
解决办法
104
查看次数

GroovyClassLoader和导入

我在我的Java类中使用GroovyClassLoader来解析某个(理想情况下很复杂的)groovy文件(将在下一步执行):

在MyClass.java中调用

final Class parsedClass = groovyClassLoader.parseClass(groovyFile);
Run Code Online (Sandbox Code Playgroud)

知道:

  • Groovy文件需要存储在文件系统中,因为需要在不重新部署的情况下进行更改.
  • 这个groovy文件需要几个导入:

GroovyFile.groovy进口

import com.my.import.one.Import1DTO
import com.my.import.two.Import2DTO
import com.my.import.three.Import3DTO
import com.my.import.four.Import4DTO
import com.my.import.five.Import5DTO
Run Code Online (Sandbox Code Playgroud)

当调用parseClass方法时,此异常引发:

例外

unable to resolve class com.my.import.one.Import1DTO;
unable to resolve class com.my.import.two.Import2DTO;
unable to resolve class com.my.import.three.Import3DTO;
unable to resolve class com.my.import.four.Import4DTO;
unable to resolve class com.my.import.five.Import5DTO;
Run Code Online (Sandbox Code Playgroud)

在解析基类之前,我是否可以获得我期望的行为而不解析每个导入类?

谢谢!

groovy groovyshell groovyclassloader java-7

5
推荐指数
1
解决办法
2655
查看次数

Java8中的GroovyShell:内存泄漏/重复的类[提供了src代码+负载测试]

由GroovyShell / Groovy脚本引起的内存泄漏(请参阅最后的GroovyEvaluator代码)。主要问题是(从MAT分析器复制粘贴):

由“ <系统类加载器>”加载的类“ java.beans.ThreadGroupContext”占用807,406,960(33.38%)个字节。

和:

由“ sun.misc.Launcher $ AppClassLoader @ 0x7004e9c80”加载的“ org.codehaus.groovy.reflection.ClassInfo $ ClassInfoSet $ Segment”的16个实例占用1,510,256,544(62.44%)字节

我们正在使用Groovy 2.3.11和Java8(确切地说是1.8.0_25)
升级到Groovy 2.4.6不能解决问题。只是提高了内存使用一个 一点,ESP。非堆。
我们正在使用的Java参数:-XX:+ CMSClassUnloadingEnabled -XX:+ UseConcMarkSweepGC

顺便说一句,我已阅读https://dzone.com/articles/groovyshell-and-memory-leaks。当不再需要GroovyShell shell时,我们会将其设置为null。使用GroovyShell()。parse()可能会有所帮助,但这对我们来说不是一个选择-我们有10多个集合,每个集合由20-100个脚本组成,并且可以随时更改(在运行时)。

设置MaxMetaspaceSize也应该有所帮助,但这并不能真正解决根本问题,也不能消除根本原因。所以我仍在努力确定。


我创建了负载测试来重新创建问题(请参阅最后的代码)。当我运行它时:

  • 堆大小,元空间大小和类数不断增加
  • 几分钟后进行的堆转储大于4GB

前3分钟的效果图: 在此处输入图片说明

正如我已经提到的,我正在使用MAT分析堆转储。因此,让我们检查Dominator树报告:

在此处输入图片说明

Hashmap占用了30%以上的堆。因此,让我们进一步分析它。让我们看看里面有什么。让我们检查哈希条目:

在此处输入图片说明

报告了38 830个条目。包括38780个条目,这些条目的键匹配“ .class Script。 ”。

另一件事,“重复的类”报告:

在此处输入图片说明

我们有400个条目(因为负载测试定义了400个G.script),所有这些条目都属于“ ScriptN”类。它们都持有对groovyclassloader $ innerloader的引用

我发现了类似的错误报告:https : //issues.apache.org/jira/browse/GROOVY-7498(请参阅最后的评论和屏幕截图)-通过将Java升级到1.8u51解决了他们的问题。但是,这对我们并没有招数。

我们的代码:

public class GroovyEvaluator
{
    private GroovyShell shell;

    public GroovyEvaluator()
    { …
Run Code Online (Sandbox Code Playgroud)

memory-leaks groovyshell groovyclassloader java-8

5
推荐指数
1
解决办法
2763
查看次数

如何在隔离的类加载器中执行groovy脚本?

我正在尝试在隔离的类加载器中运行groovy脚本,以便它们不会在调用类的依赖项的上下文中执行.

    Path log4j = Paths.get("..../lib/log4j-1.2.17.jar");
    Path groovy = Paths.get("..../lib/groovy-all-2.1.3.jar");
    RootLoader rootLoader = new RootLoader(new URL[] { log4j.toUri().toURL(), groovy.toUri().toURL() }, null);
    GroovyScriptEngine engine = new GroovyScriptEngine(".../src/main/resources", rootLoader);
    engine.run("Standalone.groovy", "");
Run Code Online (Sandbox Code Playgroud) Standalone.groovy:
import org.apache.log4j.BasicConfigurator
import org.apache.log4j.Logger

Logger logger = Logger.getLogger(getClass())
BasicConfigurator.configure()
logger.info("hello world")
Run Code Online (Sandbox Code Playgroud) pom.xml摘录:
    <dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy-all</artifactId>
        <version>2.1.3</version>
    </dependency>
Run Code Online (Sandbox Code Playgroud)

我试过的上述任何变化都会导致

Exception in thread "main" groovy.lang.GroovyRuntimeException: Failed to create Script instance for class: class Standalone. Reason: java.lang.ClassCastException: Standalone cannot be cast to groovy.lang.GroovyObject
    at org.codehaus.groovy.runtime.InvokerHelper.createScript(InvokerHelper.java:443)
    at groovy.util.GroovyScriptEngine.createScript(GroovyScriptEngine.java:564)
    at groovy.util.GroovyScriptEngine.run(GroovyScriptEngine.java:551)
    at groovy.util.GroovyScriptEngine.run(GroovyScriptEngine.java:537) …
Run Code Online (Sandbox Code Playgroud)

java groovy classloader urlclassloader groovyclassloader

5
推荐指数
1
解决办法
428
查看次数

加载类路径中不存在的类

假设我使用Groovyc编译了一个Groovy脚本,它在文件系统中生成了一个或多个.class文件.从Java应用程序中,如何动态地将这些类添加到类路径中以加载它们并调用它们的方法?目标是预编译Groovy脚本并将它们存储到数据库中,因此可以从脚本的编译版本执行评估.

java groovy classpath classloader groovyclassloader

3
推荐指数
1
解决办法
3748
查看次数

如何从Java评估我自己的Groovy脚本?

我尝试从Java类调用我自己的groovy脚本函数,用户也可以使用标准表达式.

例如:

GroovyShell shell = new GroovyShell();
Script scrpt = shell.parse("C:/Users/Cagri/Desktop/MyCustomScript.groovy");

Binding binding = new Binding();
binding.setVariable("str1", "foo");
binding.setVariable("str2", "boo");             

scrpt.setBinding(binding);
System.out.println(scrpt.evaluate("customConcat(str1, str2)")); //my custom method
System.out.println(scrpt.evaluate("str1.concat(str2)"));
Run Code Online (Sandbox Code Playgroud)

这是MyCustomScript.groovy

def area(def sf) {
    Feature f = new Feature(sf);
    f.getGeom().area;
}

def customConcat(def string1, def string2) {
    string1.concat(string2)
}
Run Code Online (Sandbox Code Playgroud)

运行时,此行scrpt.evaluate("str1.concat(str2)")按预期工作,但scrpt.evaluate("customConcat(str1, str2)")会引发异常:

groovy.lang.MissingMethodException: No signature of method: Script1.customConcat() is applicable for argument types: (java.lang.String, java.lang.String) values: [foo, boo]
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:55)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:78)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:145)
at …
Run Code Online (Sandbox Code Playgroud)

java groovy groovyshell scriptengine groovyclassloader

3
推荐指数
1
解决办法
6630
查看次数

Groovy动态调用类和find方法不起作用?

我试图建立一个类似于的动态查询:

def domain = DomainName
def ids = 1
def domainClass = "$domain" as Class
domainClass.find("from ${domain} as m where m.job = ${ids} ").id
Run Code Online (Sandbox Code Playgroud)

但它不起作用.

如果我正在尝试这个,一切都很好:

def domain = DomainName
def ids = 1
DomainName.find("from ${domain} as m where m.job = ${ids} ").id
Run Code Online (Sandbox Code Playgroud)

如何在find中使用动态域名类?

grails groovy grails-orm groovyclassloader

2
推荐指数
1
解决办法
3595
查看次数

如何编译 Groovy 源代码而不是从文件系统

我使用 GroovyClassLoader.parseClass(src) “即时”编译单个 groovy 源模块,一切正常。

但问题是当这个源模块导入其他类时,这些类还没有编译。当我开始编译一个源代码但其他源代码是必需的并且在源路径上准备就绪时,传统编译也会进行编译。

如何使用带有目标的 GroovyClassLoader 来编译所有其他所需的源而不是来自 FILESYSYSTEM。我的来源例如在数据库中、通过 URI 的远程 http 等。

groovy groovyclassloader

1
推荐指数
1
解决办法
604
查看次数