Groovy的classloader加载机制唤起的频繁GC

来源:本网整理

●是一个基于 Java虚拟机的敏捷 动态语言。构建在强大的Java语言之上 并 添加了从Python,Ruby和Smalltalk等语言中学到的 诸多特征。为Java开发者提供了 现代最流行的编程语言特性,而且学习成本很低(几乎为零)。支持DSL(Domain Specific Languages领域定义语言)和其它简洁的语法,让你的代码变得易于阅读和维护。Groovy拥有处理原生类型,面向对象以及一个Ant DSL,使得创建Shell Scripts变的非常简单。在开发Web,GUI,数据库或控制台程序时 通过 减少框架性代码 大大提高了开发者的效率。支持单元测试和模拟(对象),可以 简化测试。无缝集成 所有已经存在的 Java对象和类库。直接编译成Java字节码,这样可以在任何使用Java的地方 使用Groovy。Groovy 的一个好处是,它的语法与 Java 语言的语法很相似。虽然 Groovy 的语法源于 Smalltalk 和 Ruby 这类语言的理念,但是可以将它想像成 Java 语言的一种更加简单、表达能力更强的变体。(在这点上,Ruby 与 Groovy 不同,因为它的语法与 Java 语法差异很大。Groovy 快捷方式 开始使用 Groovy 时,您会发现它使日常的编程活动变得快了许多。完成本教程之后,您会了解更多的 Groovy 语法快捷方式。不过现在只需知道以下这些要点:Groovy 的松散的 Java 语法允许省略分号和修改符。除非另行指定,Groovy 的所有内容都为 public。Groovy 允许定义简单脚本,同时无需定义正规的class 对象。Groovy 在普通的常用 Java 对象上增加了一些独特的方法和快捷方式,使得它们更容易使用。Groovy 语法还允许省略变量类型。Groovy 的新增特性 虽然Groovy 允许省略 Java 语法中的一些元素,但也增加了一些新特性,例如本地集合、内置的正则表达式和闭包。在标准的 Java 代码中,如果想要创建一个项列表,首先要导入<code>java.util.ArrayList,然后程序化地初始化<code>ArrayList实例,然后 再向实例中添加项。在 Groovy 中,列表和映射都内置在语法中—无需导入任何内容。正则表达式也不需要额外的导入或对象;它们可以通过特殊的 Groovy 语法来创建。关于闭包 对于任何 Java 开发人员来说,闭包都是一个令人兴奋的新技巧。这些神奇的构造将会包含在未来的 Java 发行版(很可能是 Java 7)中,成为正式的 Java 语法,但现在已经可以在 Groovy 中使用了。可以将闭包 想像为一个代码块,可以现在定义,以后再执行。可以使用这些强大的构造做许多漂亮的事,不过最著名的是简化迭代。使用 Groovy 之后,就有可能再也不需要编写Iterator 实例了。动态的 Groovy 从技术上讲,Groovy 可能是您最近听说过的类型最松散的动态语言之一。从这个角度讲,Groovy 与 Java 语言的区别很大,Java 语言是一种固定类型语言。在 Groovy 中,类型是可选的,所以您不必输入String myStr="Hello;来声明 String 变量,可以使用def myStr="Hello;(分号可有可无)。除此之外,Groovy 代码还能在运行时轻松地改变自己。这实际上意味着,能够在运行时轻松地为对象指定新方法和属性。这一编程领域称为元编程,Groovy 能够很好地支持这种编程方式。在学习本教程的过程中,您将了解到关于 Groovy 的动态性质的更多内容。现在惟一要补充的是,您会惊讶地发现,在 Groovy 会使操作 XML 或普通的 java.io.File 实例变得非常轻松。一体两面 用Groovy 编写的任何内容都可以编译成标准的 Java 类文件并在 Java 代码中重用。类似地,用标准 Java 代码编写的内容也可以在 Groovy 中重用。所以,可以轻易地使用 Groovy 为 Java 代码编写单元测试。而且,如果用 Groovy 编写一个方便的小工具,那么也可以在 Java 程序中使用这个小工具。Groovy是用Java实现的开源脚本语言并且和它联系紧密.它需要JDK 1.4.Groovy向Java添加了许多Ruby和Python脚本语言的特性.Groovy的特性包括动态类型(dynamic typing),闭包(closures),简单对象导航(easy object navigation)和更加简洁的Lists和Maps语法.Groovy是由James Strachan和Bob McWhirter创造的.James还参与了许多其他开源项目的开发,其中包括Jelly,dom4j,Jaxen,Betwixt和Maven.Bob是Jaxen和Drools(一个开源的面向对象的JAVA规则引擎)的创始人.目前最新稳定版为Groovy1.8www.zgxue.com防采集请勿采集本网。

Groovy的classloader加载机制引起的频繁GC

GROOVY的classloaer机制 

能在 Java 虚拟机执行的脚本语言,在众多脚本语言中应用面不算广,选择Groovy的原因一般对Java比较熟,而又需要使用一些动态的脚本的功能。你可以把它作为是对Java语言的无缝扩展。关于前景,

Groovy嵌入到JAVA里面执行有一种方式在通过使用GroovyClassLoader将Groovy的类动态地载入到Java程序中并直接使用或运行它.

说的是groovy everywhere,但是不是aomg的 是社长和chacha开的另一个公司 叫H1ghr music 里面有外国和韩国的艺人 都是很有实力但是不怎么火的 groovy room具体两个人是谁你可以去微博查查我也忘

例如:

ClassLoader parent = getClass().getClassLoader(); GroovyClassLoader loader = new GroovyClassLoader(parent); Class groovyClass = loader.parseClass(new File("src/main/groovy/script/Test.groovy")); // 调用实例中的某个方法 GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance(); Object[] args = {}; groovyObject.invokeMethod("run", args);

groovy 英[?gru:vi]美[?ɡruvi] adj.绝妙的;槽的,沟的;流行的;最佳状态的;[例句]Once again,I am taking advantage of the seamless integration between the Java language and Groovy. 我

产生脚本:

GroovyClassLoader groovyClassLoader = new GroovyClassLoader(); Class<?> scriptClass =groovyClassLoader.parseClass(scriptCode); return InvokerHelper.createScript(scriptClass, binding);?

一种基于Java虚拟机的动态语言,可以和java无缝集成,正是这个特性,很多时候把二者同时使用,把groovy作为java的有效补充。对于Java程序员来说,学习成本几乎为零。同时支持DSL和其他简介的语法(例如

频繁GC的问题

groovy KK:[] DJ:[] a. 1.【俚】绝妙的;时髦的 2.墨守成规的 以上结果由 Dr.eye译典通字典 提供 groove KK:[] DJ:[] n.[C] 1.沟;槽;(车)辙;(唱片)纹(道) Wheels leave grooves in a dirt road.

   项目环境:groovy1.8.4 + jdk1.6

     在一次应用开发中被性能测试同学发现有内存泄漏,内存回收异常。每4分钟FGC一次。并且由old区内存情况发现内存泄露现象;经定位,发现在OLD区有大量的GROOVY脚本存在,导致频繁FULL GC;在GROOVY的脚本执行代码里面,当从CACHE里面获取到groovy脚本的字符串时,调用

scriptClass = groovyClassLoader.parseClass(scriptCode)

解析生成groovy脚本,GroovyClassLoader是GROOVY自带的类加载器,继承JAVA的URLClassLoader,其实质就是将GROOVY脚本变成class,这个过程会消耗CPU和内存,同时由于GROOVY在加载每个脚本的时候,都在脚本前面增加了

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

的代码,导致对任何一次脚本解析都产生一个新的脚本,这样反应在页面上就是相当于每刷新一次,就会产生一批新的脚本,当做性能测试,压上很多用户的时候,就会导致大量的脚本对象产生,从而导致了OLD存在大量的groovy script脚本,最终引起频繁的GC(每4分钟一次);

   解决的方式是在程序里面采用一个全局的MAP,对于同样的groovy 的script脚本,只调用

scriptClass = groovyClassLoader.parseClass(scriptCode)

一次,然后将生成的script对象存放在map中,这样来避免每个脚本每次调用都产生新的script对象;修改之后,在同样的性能测试条件下,每1.5小时也没有full gc;

  其实仔细想想,groovy用这种方式来保持其动态性,每次动态加载class(or脚本),这样的话当修改了脚本之后,立即生效;但是这样的机制必然带来的是新能的损耗。

下面的代码测试了GROOVY动态执行带来的成本损耗:

import groovy.lang.Binding;import groovy.lang.GroovyClassLoader;import groovy.lang.Script;import java.util.HashMap;import java.util.Map;import org.codehaus.groovy.runtime.InvokerHelper;import org.junit.Test;public class BaseTestCase {private static Map<String, Script> scripts = new HashMap<String, Script>();@Testpublic void test() {// fail("Not yet implemented");long time1 = test_execute(false);System.out.println("------------------------------------------------------\n");long time2 = test_execute(true);System.out.println(time1 / time2);}public long test_execute(boolean isCached) {// groovy脚本String scriptStr = "def execute(Map temp){return [\"result\":\"hello world\" + temp.a]}";// def code = new Source(source: script,type: "new",name: "hello")Map<String, Object> context = new HashMap<String, Object>();long start = System.currentTimeMillis();for (int i = 0; i < 1000; i++) {Map<String, Object> params = new HashMap<String, Object>();params.put("a", "b" + i);excute(context, params, scriptStr, isCached);}long time = System.currentTimeMillis() - start;System.out.println("take time: " + time);return time;}/** * 将脚本源码分析成Script对象 * * @param key * 将作为class name * @param scriptCode * 脚本源码 * @return script对象 */private Script parseScript(String[] args, String scriptCode,boolean isCached) {try {Script script = scripts.get("1");if (!isCached || script == null) {GroovyClassLoader groovyClassLoader = new GroovyClassLoader();Class<?> scriptClass = groovyClassLoader.parseClass(scriptCode);Binding context = new Binding(args);script = InvokerHelper.createScript(scriptClass, context);}if(isCached){scripts.put("1", script);}return script;} catch (Throwable e) {return null;}}private void excute(Map<String, Object> contentx,Map<String, Object> params, String code, boolean isCached) {String[] args = new String[] { "aaa", "ddd" };Script script = parseScript(args, code, isCached);Map<String, Object> result = (Map<String, Object>) script.invokeMethod("execute", params);for (Map.Entry<String, Object> entry : result.entrySet()) {System.out.println(entry.getValue());}}}

执行的结果:

take time: 9585------------------------------------------------------take time: 16599

没有缓存的代码的执行时间是有缓存的600倍,这个差距还是有点大的;

params?email就是参数email的意思param[释义]参数;[网络]氰胍;[例句]The fourth param here is an array of options.第四个参数是一个选项数组。相关单词:PARAM abbr.parametrical 参数的,参量的Groovy是一种基于JVM(Java虚拟机)的敏捷开发语言,它结合了Python、Ruby和Smalltalk的许多强大的特性,Groovy 代码能够与 Java 代码很好地结合,也能用于扩展现有代码内容来自www.zgxue.com请勿采集。

免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
Copyright © 2017 www.zgxue.com All Rights Reserved