Common pit of groovy and Java integration — turn

https://yq.aliyun.com/articles/2357

Groovy is not only a dynamic language based on JVM, but also an object-oriented language, which is very similar to Java in syntax. It combines many powerful features of python, ruby and Smalltalk. Groovy code can be well combined with java code and can also be used to extend existing code. As a general and static compiled language, Java has many advantages, but it also has some burdens: recompiling is too labor-consuming; The static type is not flexible enough, and the reconstruction time may be long; The deployment is too noisy; The syntax of Java is not suitable for DSL production; Java is not an ideal language to solve dynamic layer problems, including prototype design, script processing and so on. Groovy can be regarded as a language that adds dynamic capabilities to the static world of Java. At the same time, groovy has implemented language features that Java does not have:

Revisit how groovy calls Java, including using groovyclassloader, groovyshell and groovyscript engine.

Groovyshell allows you to find the value of any groovy expression in Java classes (or even groovy classes). You can use the binding object to enter parameters to the expression, and finally return the evaluation result of the groovy expression through groovyshell.

Groovy shell is mostly used to deduce opposing scripts or expressions. If you change to multiple scripts related to each other, it will be better to use groovy script engine. Groovyscriptengine loads groovy scripts from the location you specify (file system, URL, database, etc.) and reloads them as the scripts change. Like groovyshell, groovyscriptengine allows you to pass in parameter values and return script values.

As a JVM based language, groovy can easily interoperate with Java, but it also needs to be compiled into a class file before it can run. Therefore, understanding the corresponding relationship between groovy code file and class file is helpful to better understand the operation mode and structure of groovy.

If the groovy script file contains only execution code and no class is defined, the compiler will generate a subclass of the script with the same class name as the file name of the script file, and the script code will be included in a method named run. At the same time, a main method will be generated as the entry of the whole script.

If the groovy script file contains only one class, and the name of this class is consistent with the name of the script file, it is the same as Java, that is, generate a class file consistent with the defined class.

If the groovy script file contains multiple classes, the groovy compiler is happy to generate a corresponding class file for each class. If you want to execute the script directly, the first class in the script must have a static main method.

If the groovy engine is embedded in the application, it will dynamically execute the incoming expression and return the execution result. Every time groovy executes the script, it will generate a class object corresponding to the script and load the object with a new innerloader. Neither innerloader nor script object can be recycled during GC. After running for a period of time, perm will be full and fullgc will be triggered all the time. Why does groovy generate a class object corresponding to the script every time it executes the script? A classloader can only load a class with the same name once, which is loaded by groovyclassloader. Then, when a script defines a C class and another script defines a C class, groovyclassloader cannot load. Why does it load every execution here? This is because for the same groovy script, the groovy execution engine will be named differently, and the naming is related to the timestamp. When text is passed in, the naming rule of class object is: "script" + system currentTimeMillis() + Math. abs(text.hashCode()) + ".groovy"。 This causes that even if the groovy script does not change, each time the parse method is executed, a new class object corresponding to the script will be generated and loaded by the groovyclassloader, increasing the perm area. Why can't the corresponding loaded by innerloader be cleaned up by GC? As we all know, a class in the JVM can only be recycled by GC if it meets the following three conditions, that is, the class is unloaded: 1 All instances of this class have been GC, that is, there is no instance of this class in the JVM; 2. The classloader that loads this class has been GC; 3. Java Lang. class object is not referenced anywhere, for example, the method of this class cannot be accessed anywhere through reflection. There is a class object cache in the groovyclassloader code. Further, it is found that this object will be cached in the map every time the script is compiled, that is, setclasscacheentry (clazz). Every time groovy compiles a script, the class object of the script will be cached. The next time the script is compiled, it will be read from the cache first, so as to save compilation time. The cached map is held by groovyclassloader, and the key is the class name of the script. As a result, the class object corresponding to each script has references and cannot be cleaned up by GC. How to solve it? Please refer to:. For a deeper understanding of the groovyclass loader system, please refer to the following article

Groovy scripts are usually executed in Java using the following code: groovyclass = (class

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>