Too many classes in groovy CallSiteClassLoader - groovy

In our application we embed groovy 1.8.9 jar and invoke a groovy script from Java code at run time. The groovy scripts are not changing in each call and can be considered fixed logic.
When we run the application for a long time we see too many classes in org/codehaus/groovy/runtime/callsite/CallSiteClassLoader
in fact for each call, we see a class being generated. This leads to GC pressure and unpleasant side effects.
since our groovy scripts are unchanged from call to call, is there a way to reuse the callsite classes generated once.

Related

Groovy getSAMMethodImpl() Method Performance

I'm running a profiler against a running Java service (Spring Boot framework), containing multiple Groovy files all with the #CompileStatic annotation.
Now one of the most time consuming methods is an internal Groovy method (getSAMMethodImpl()). I've been unsuccessful tracking down what this method is actually doing under the covers.
What exactly does this method do, and is there any way to prevent it from being called?
This method gets executed when a CachedClass for a class with a single abstract method (aka SAM) is created. Cached classes are Groovy mechanism to deal with a reflection in a more effective way - instead of always retrospecting classes from the beginning at the runtime it remembers e.g. modifications applied with metaprogramming (adding new methods to classes for instance), so it gets all class information very quickly. Of course it comes with some overhead.
For instance, when the meta class registry is initialized (once), it registers about 1180 methods. About 190 of them cause CachedSAMClass.getSAMMethodImpl(Class<?> c) to be executed. It happens, because ClassInfo.isSAM(Class<?> c) which checks if given class is a single abstract method class calls this method. And if you take a look at ClassInfo.createCachedClass(Class klazz, ClassInfo classInfo) you will see that this isSAM() method gets called always as a last check.
In most cases creating a registry of cached classes shouldn't be a problem - it happens one time for each class. Most of them get registered when you simply access metaClass property of any class. Or when you create a first closure. When it comes to performance, many different factors matter. For instance, Spring Boot uses hot swapping to reload classes at the runtime. In this case Groovy meta class registry gets recreated and all cached classes have to be recreated as well. The same thing may happen when you run a Spring Boot application with spring-boot-devtools dependency added - it uses additional class loader called RestartClassLoader which requires additional meta class registry to be initialized. Actually the number of class loaders you have, that number of times meta class registry will be initialized (once for each class loader). This RestartClassLoader also causes recreating cached classes when it restarts.
And last but not least - if you want to measure performance correctly, try doing it on a production server instead of a local dev environment. If you can attach a debugger to the running process on a server and put a breakpoint in CachedSAMClass.getSAMMethodImpl(Class<?> c) at line 169, you can see how many times and for what classes this method gets executed. If it happens that it gets executed multiple times for the same class, it may suggest that your application is restarting class loader and Groovy has to rebuild meta class registry. It shouldn't happen - production application once started should not make any changes to class loader without a purpose. It is acceptable on a local dev - devtools and hot swapping will force meta class registry to be recreated any time class loader gets refreshed.

TestNG: Run only one method/class "singlethreaded"*

I have to test one class for it's output to System.out. To do so I redirect System.out to my OutputStream, let my method output it's stuff and check what my stream has recorded. Afterwards i restore System.out.**
All fine until there are other threads which are run in parallel and write to stdout. So things get mixed up and my tests fail.
Is there a method (preferably via annotations) to tell TestNG to run this test-class/-method without running another test in parallel while keeping the other classes running parallel?
Thanks a lot
*) "singlethreaded" is not the right word here but I don't know a better one to put it in headlines.
**) I know that this is a bit hacky but I can't inject a stream to this class for reasons so ancient only the balrog knows.

Groovy script: How to safeguard against possible memory leak or infinite loops

We intend to allow our clients to execute their own groovy scripts within our platform. They will be allowed to access only controlled methods but we have one concern.
Although we will take all possible care somewhere we might get into a risk of long running loops - resulting in memory leak or infinite loop which can affect our platform.
Is there any inherent way within groovy script to protect against such probability?
You can prevent loops and all dangerous syntax constructs with a SecureASTCustomizer.
Nice article here.
If you can restrict your DSL (the code your client can run) so that it can only invoke your methods on your object(s), it's up to you to guarantee memory cannot leak or be abused in any way.
Build your GroovyShell by passing it a custom CompilerConfiguration
Build your custom CompilerConfiguration with a custom SecureASTCustomizer using method addCompilationCustomizers(...)
You probably want to get all function calls in your DSL to go through a custom class of yours. For that, have your shell parse the script, cast the script as a DelegatingScript and pass it your object:
DemoDSLHelper delegate = new DemoDSLHelper(); // Your custom class with custom methods you want to expose in the DSL
GroovyShell shell = new GroovyShell(createCompilerConfiguration());
Script script = shell.parse(scriptText);
((DelegatingScript)script).setDelegate(delegate);
Object result = script.run();
Run that in a separate JVM, so that you can enforce limits on the process with OS-dependent primitives for that (containerization, etc), or simply kill it if it fails to respect your rules (duration, resources consumption, etc). If it must run within a JVM that does other things, at the very least you'll need to be extremely restrictive in what you accept in the DSL.
And here a gist with complete runnable example.

Is there a way to declare a class inside a try and catch block in jscript?

I want to use System.Threading methods provided by the .NET. for creating 2 test conditions that must happen simultaneously.
Using this solution to put the function in a class I was able to create 2 threads and run them parallely in jsc compiler.
But the environment I am writing my test scripts in, places my entire code in a try block and then compiles, which throws the
error:JS1109: Class definition not allowed in this context.
Is there anyway to make multithreading possible without the use of classes in JScript?

Can i call a gradle task from a groovy method in a .gradle file?

I have a non conventional build script in gradle that does cyclic compiling of projects.
It's gonna take weeks to change to standard gradle build so that's not gonna happen now.
The issue is I want to stop using ant in my script and move to use groovy + gradle only.
The question is how to change tasks like copy ? replaceregexp ? unzip ?
I assume in the standart gradle plugin and java plugin I have most of what i need, but they are all tasks, now if i have in my main task a method that needs copy operation, how do I got about ?
Is there a way to call the tasks code ? Is there a way to call the task itself from a groovy script ?
First of all, you should never call a task from another task - bad things will happen if you do. Instead, you should declare a relationship between the two tasks (dependsOn, mustRunAfter, finalizedBy).
In some cases (fewer than people tend to believe), chaining tasks may not be flexible enough; hence, for some tasks (e.g. Copy) an equivalent method (e.g. project.copy) is provided. However, these methods should be used with care. In many cases, tasks are the better choice, as they are the basic building blocks of Gradle and offer many advantages (e.g. automatic up-to-date checks).
Occasionally it also makes sense to use a GradleBuild task, which allows to execute one build as part of another.

Resources