【问题标题】:Is hot code replace supposed to work for Groovy in Eclipse?热代码替换是否应该适用于 Eclipse 中的 Groovy?
【发布时间】:2015-06-30 00:11:24
【问题描述】:

我想知道是否有人能够让 Groovy 热替换在 Eclipse 中可靠地工作。我找不到任何有用的信息,所以我不确定它是否是 b/c 它只是为其他人工作?还是没有人使用 Eclipse 进行 Groovy 开发?

我已经尝试使用最新的 Eclipse (4.5 Mars) 和最新的 Groovy-Eclipse 插件(来自http://dist.springsource.org/snapshot/GRECLIPSE/e4.5/ 的 Groovy Eclipse 2.9.2),但我仍然无法获得可靠的热替换。

一些简单的热替换方案可以正常工作。但是,稍微复杂一点就会导致奇怪的 Groovy 异常。我在不同的情况下会遇到不同的错误,但我能够在一个简单的 junit 中重现一个错误,所以我将使用一些简化的域对象来演示这个错误。

HotSwapTests.groovy

class HotSwapTests {
    @Test
    public void testHotReplace() {
        DefaultTxView transactionGroup = new DefaultTxView();

        List<Default> defaults = [];

        Default d1 = new Default(ProducerAccountTransactionType.REPAID_AMOUNT, ParticipantAccountType.DEFAULT);
        Default d2 = new Default(ProducerAccountTransactionType.REPAID_AMOUNT, ParticipantAccountType.DEFAULT);

        d1.setCancelledDefault(d2);

        defaults << d1;

        transactionGroup.setDefaultTransactions(defaults);


        while (true) {
            Default result = transactionGroup.getRepaymentTransaction();
            println result
        } 
    }
}

DefaultTxView.groovy

public class DefaultTxView {

    def List<Default> defaultTransactions;

    public Default getRepaymentTransaction() { return getTransactionOfType(REPAID_AMOUNT); }

    public Default getTransactionOfType(ProducerAccountTransactionType type) {
        return defaultTransactions.find { it.getType() == type };
    }

Default.java

The contents of this domain object are not really important - it's a simple POJO.

现在,为了测试热插拔,我在标记的行放置了一个断点:

while (true) {
    Default result = transactionGroup.getRepaymentTransaction(); <<< break
    println result
} 

然后我去DefaultTxView.groovy修改传入find方法的闭包里面的代码:

public Default getTransactionOfType(ProducerAccountTransactionType type) {
    return defaultTransactions.find { it.getType() == type && it.getCancelledDefault() == null};
}

我在保存文件时没有收到任何警告或错误消息,但如果我现在尝试跨过修改的行,我会收到以下异常:

java.lang.ArrayIndexOutOfBoundsException: 2
    at ca.gc.agr.app.web.jsf.producer.DefaultTxView$_getTransactionOfType_closure1.doCall(DefaultTxView.groovy:15)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:278)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1016)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:39)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.BooleanReturningMethodInvoker.invoke(BooleanReturningMethodInvoker.java:48)
    at org.codehaus.groovy.runtime.callsite.BooleanClosureWrapper.call(BooleanClosureWrapper.java:50)
    at org.codehaus.groovy.runtime.DefaultGroovyMethods.find(DefaultGroovyMethods.java:3060)
    at org.codehaus.groovy.runtime.dgm$175.invoke(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:271)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at ca.gc.agr.app.web.jsf.producer.DefaultTxView.getTransactionOfType(DefaultTxView.groovy:15)
    at ca.gc.agr.app.web.jsf.producer.DefaultTxView$getTransactionOfType$1.callCurrent(Unknown Source)
    at ca.gc.agr.app.web.jsf.producer.DefaultTxView.getRepaymentTransaction(DefaultTxView.groovy:11)
    at ca.gc.agr.app.web.jsf.producer.DefaultTxView$getRepaymentTransaction$0.call(Unknown Source)
    at ca.gc.agr.app.web.jsf.temp.HotSwapTests.testHotReplace(HotSwapTests.groovy:29)

在 TomCat 中运行我的 web 应用程序时,我得到了非常相似的结果,修改该行后出现了同样的异常。重新启动junit,或者TomCat 使新线路工作正常,所以这绝对是一个热替换问题。

那么我做错了什么?任何建议将不胜感激。

【问题讨论】:

    标签: eclipse debugging groovy


    【解决方案1】:

    我过去使用 eclipse 插件在 web 开发环境 with groovy successfully 中使用过热部署。

    IIRC,我使用了 groovyReset.jar、DCEVM 和 jdk1.7。

    groovyReset.jar 应该在类路径中并设置为java agent。我使用了 groovy-eclipse 插件文件夹中的那个(比如eclipse/plugins/org.codehaus.groovy_2.3.7.xx-201411061335-e44-RELEASE/extras/groovyReset.jar

    -javaagent:/groovyReset.jar

    无需重新部署即可立即看到新的闭包和方法。当然,在方法中包含一个简单的 LOC 也可以。有时我需要重新启动 VM,但仍然可以呼吸新鲜空气。


    在您的情况下,我认为至少 groovyReset.jar 必须存在。它负责重置元类。如果你反编译一个 groovy 类,你可以使用 java.lang.Method 的数组检查通过反射调用的方法调用。在热代码交换时,此数组出现故障,需要重置。

    【讨论】:

      猜你喜欢
      • 2013-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多