首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

在java中使用groovy如何搞 (java and groovy)

2014-01-21 
在java中使用groovy怎么搞(java and groovy)什么是groovy?一种基于Java虚拟机的动态语言,可以和java无缝集

在java中使用groovy怎么搞 (java and groovy)

什么是groovy?

一种基于Java虚拟机的动态语言,可以和java无缝集成,正是这个特性,很多时候把二者同时使用,把groovy作为java的有效补充。对于Java程序员来说,学习成本几乎为零。同时支持DSL和其他简介的语法(例如闭包),使代码便于阅读。可以用groovy的动态特性来做规则引擎,在DB中维护脚本,业务变化的时候让应用系统动态加载。

?

如果引入groovy在java工程中?

这个很简单,不需要做别的事情,仅仅把groovy的二方包加入到pom文件中即可。例如:

12345<dependency>??????<groupId>org.codehaus.groovy</groupId>??????<artifactId>groovy-all</artifactId>??????<version>1.8.3</version></dependency>

?

java和groovy混合使用的方法有几种?

?

1、静态编译,在java工程中直接写groovy的文件,然后可以在groovy的文件中引用java工程的类,这种方式能够有效的利用groovy自身的语言特性,例如闭包;

?

2、通过groovyShell类直接执行脚本,例如:

12345678910111213package?groovy_dsl.shell;import?groovy.lang.Binding;import?groovy.lang.GroovyShell;public?class?GroovyShellEx {????????public?static?void?main(String[] args) {????????????????Binding bind =?new?Binding();????????????????bind.setVariable("name",?"iamzhongyong");????????????????bind.setVariable("age",?"25");???????????????????????GroovyShell shell =?new?GroovyShell(bind);???????????????????????????????Object obj = shell.evaluate("str = name+age;return str");???????????????????????????????System.out.println(obj);????????}}

?

3、通过groovyScriptEngine执行文件或者脚本,例如:

123456789package?groovy_dsl.script;import?groovy.util.GroovyScriptEngine;public?class?ScriptEngine {????????public?static?void?main(String[] args)?throws?Exception {????????????????GroovyScriptEngine engine =?new?GroovyScriptEngine("");???????????????????????????Object obj = engine.run("src/main/java/groovy_dsl/script/script_test.groovy",?"iamzhongyong");????????????????????????????System.out.println(obj);????????}}

?

?4、通过GroovyClassLoader来执行,例如:

123456789101112131415161718192021222324package?groovy_dsl.classloader;import?groovy.lang.GroovyClassLoader;import?groovy.lang.GroovyObject;import?java.io.File;import?java.io.IOException;public?class?GroovyClassLoaderEx {?????????public?static?void?main(String[] args)?throws?Exception, IOException {????????????????GroovyClassLoader loader =?new?GroovyClassLoader();?????????????????for(int?i=0;i<100;i++){????????????????????????Class<?> clazz = loader.parseClass(new?File("src/main/java/groovy_dsl/classloader/UserDO.groovy"));?????????????????????????GroovyObject clazzObj = (GroovyObject)clazz.newInstance();?????????????????????????clazzObj.invokeMethod("setName",?"iamzhongyong");????????????????????????clazzObj.invokeMethod("setSex",?"Boy");????????????????????????clazzObj.invokeMethod("setAge",?"26");?????????????????????????System.out.println(clazzObj.invokeMethod("getAllInfo",?null));????????????????}?????????}}

?

使用groovy尤其需要主要的问题?

通过看groovy的创建类的地方,就能发现,每次执行的时候,都会新生成一个class文件,这样就会导致JVM的perm区持续增长,进而导致FullGCc问题,解决办法很简单,就是脚本文件变化了之后才去创建文件,之前从缓存中获取即可。

groovy中的源码如下:

1return?parseClass(text,?"script"?+ System.currentTimeMillis() + Math.abs(text.hashCode()) +?".groovy");

这个是增加缓存的代码:

123456789101112GroovyClassLoader groovyClassLoader =?new?GroovyClassLoader(GroovyScriptExecute.class.getClassLoader());Class<?> groovyClass =?null;String classKey = String.valueOf(scriptClass.hashCode());//先从缓存里面去Class文件if(GroovyScriptClassCache.newInstance().containsKey(classKey)){????groovyClass = GroovyScriptClassCache.newInstance().getClassByKey(classKey);}else{????groovyClass = groovyClassLoader.parseClass(scriptClass);????GroovyScriptClassCache.newInstance().putClass(classKey, groovyClass);}?GroovyObject go = (GroovyObject)groovyClass.newInstance();

下面这个是缓存的单例类,贴一下:

123456789101112131415161718192021public?class?GroovyScriptClassCache {????private?static?final?Map<String/*class文件的描述*/,Class<?>> GROOVY_SCRIPT_CLASS_CACHE =?new?HashMap<String,Class<?>>();?????????private?GroovyScriptClassCache(){}?????????private?static?GroovyScriptClassCache instance =?new?GroovyScriptClassCache();?????????public?static?GroovyScriptClassCache newInstance(){????????return?instance;????}?????????public?Class<?> getClassByKey(String key){????????return?GROOVY_SCRIPT_CLASS_CACHE.get(key);????}??????public?void?putClass(String key,Class<?> clazz){????????GROOVY_SCRIPT_CLASS_CACHE.put(key, clazz);????}??????public?boolean?containsKey(String key){????????return?GROOVY_SCRIPT_CLASS_CACHE.containsKey(key);????}??}

?

为啥要每次new一个GroovyClassLoader,而不是所有的脚本持有一个?

因为如果脚本重新加载了,这时候就会有新老两个class文件,如果通过一个classloader持有的话,这样在GC扫描的时候,会认为老的类还在存活,导致回收不掉,所以每次new一个就能解决这个问题了。

?

注意CodeCache的设置大小(来自:http://hellojava.info/)

对于大量使用Groovy的应用,尤其是Groovy脚本还会经常更新的应用,由于这些Groovy脚本在执行了很多次后都会被JVM编译为native进行优化,会占据一些CodeCache空间,而如果这样的脚本很多的话,可能会导致CodeCache被用满,而CodeCache一旦被用满,JVM的Compiler就会被禁用,那性能下降的就不是一点点了。

Code Cache用满一方面是因为空间可能不够用,另一方面是Code Cache是不会回收的,所以会累积的越来越多(其实在不采用groovy这种动态更新/装载class的情况下的话,是不会太多的),所以解法一可以是增大code cache的size,可通过在启动参数上增加-XX:ReservedCodeCacheSize=256m(Oracle JVM Team那边也是推荐把code cache调大的),二是启用code cache的回收机制(关于Code Cache flushing的具体策略请参见此文),可通过在启动参数上增加:-XX:+UseCodeCacheFlushing来启用。

?

参考:

http://groovy.codehaus.org/Chinese+Home

http://hellojava.info/

https://github.com/iamzhongyong/groovy_dsl?(代码在这里)

?

1 楼 JavaLanguageFun 2014-01-16   mark一个 ,最近正在找这方面的资料 2 楼 yixiandave 2014-01-16   引用通过看groovy的创建类的地方,就能发现,每次执行的时候,都会新生成一个class文件
这是个什么情况?直接创建的groovy文件也有这种问题吗?2.0以后有没有修复? 3 楼 非法用户 2014-01-16   用GroovyShell直接执行一段groovy代码,过不了多久的确会造成Perm Generation爆满
先用script = shell.parse生成script,缓存起来可以解决 4 楼 yixiandave 2014-01-16   非法用户 写道用GroovyShell直接执行一段groovy代码,过不了多久的确会造成Perm Generation爆满
先用script = shell.parse生成script,缓存起来可以解决
直接创建的groovy类不会出现这种情况吧 5 楼 非法用户 2014-01-17   yixiandave 写道非法用户 写道用GroovyShell直接执行一段groovy代码,过不了多久的确会造成Perm Generation爆满
先用script = shell.parse生成script,缓存起来可以解决
直接创建的groovy类不会出现这种情况吧
直接创建的Groovy类不会,GroovyShell动态执行一段groovy脚本是相当于在动态创建一个class,执行一次创建一个,所以才会导致Perm Generation爆满

热点排行