It may because the wrong keywords I used, not much discussion or articles found for this problem.
After loaded into JVM, is it possible to release a Class
instance automatically or manually?
- If it can be released automatically, when will this procedure be executed? Can we expect a certain time point for that?
- If it can be released manually, how? Are there some APIs?
- If it can be released no matter automatically or mannually, are we able to monitor the finalization of
Class
instances, even by using some external tools outside JVM?
Some old articles said that, if
- there is no reference to any instance / static member of a
Class
- its
ClassLoader
instance is released
that Class
will be released. Is it working for recent JVMs (for example, Oracle VM 17 or GraalVM 17)? Does it means we are able to construct some Class
for instant use and have no worry about mem-leak?
class CustomClassLoader extends java.lang.ClassLoader
{
public CustomClassLoader()
{
super(CustomClassLoader.class.getClassLoader());
}
public Class<?> loadBytes(byte[] bytecode)
{
return defineClass(null, bytecode, 0, bytecode.length);
}
}
@SneakyThrows
Object testMethod()
{
// read a Class from bytecode by a local ClassLoader
byte[] bytecode = readSomeBytesFromSomewhere();
var cl = new CustomClassLoader();
Class<?> classTest = cl.loadBytes(bytecode);
// any random code
return classTest.getMethod("testMethodInClass").invoke(null);
}
public static void main(String... args)
{
for(int step = 0; step < 9999; step )
testMethod();
}
For code above, can we consider any resource used by classTest
will be released everywhen testMethod
is done because its ClassLoader
local variable cl
is never used again?
CodePudding user response:
For code above, can we consider any resource used by classTest will be released everywhen testMethod is done because its ClassLoader local variable cl is never used again?
No, but I think you're mixing terms here. Specifically, any resource, no. Resource has a very specific meaning. will it neccessarily be released? No. Again, specific meaning.
So let me try to be specific:
Released? I think you mean Collectable
If the object created by cl.loadBytes
is garbage collectable (and from the code you showed above, it is), and all instances of it are collectable (trivially true in your example; you make no instances), and the ClassLoader object is collectable (again, in yoru code, it is), then and only then will it all be collectable.
Does that mean it'll instantly disappear? No, that is not how the garbage collector works. If the collector thinks it is necessary to do so, it'll garbage collect. If the collector does not find it neccessary, it won't. It doesn't matter to you - garbage has no effect just by existing.
Point is, your JVM won't throw an OutOfMemoryError because you have 10,000 copies of that Class
object filling up your memory.
"Released" is a word that is only used in official parlance for resources. See next section.
Resource? I think you mean Object
A resource is any object that represents a concept at the OS/Architecture level which must therefore be manually closed in order to release this resource.
An example of a 'resource' is new FileInputStream
. That is an object that is a resource - you do not rely on the garbage collector to clean this up, because the garbage collector is free to decide that this particular object needs to be cleaned up many 5 days from now. If there's plenty of heap, why bother. This isn't academic - that really happens. Hence, do not, ever, open resource objects without using try-with-resources
(or loading them in an object that itself implements AutoClosable
, so that the user of your code can do so). It's the only safe way.
This is called 'releasing'.
What you're asking about is related to resources and releasing resources the same way guns and related to grandmas: Not - at - all.
If you want to use a resource, you use try-with:
// bad:
void foo() throws IOException {
var in = new FileInputStream(...);
// do stuff with 'in'
in.close();
}
// good:
void foo() throws IOException {
try (var in = new FileInputStream(...)) {
// do stuff with 'in
}
}
ClassLoader shenanigans don't change that at all. It is not possible to 'automatically release' resources without using try-with or manually rolling out a try/finally loop.