From 5de78bb4cb96eb68cc35952c1e09b55a1a6a6e43 Mon Sep 17 00:00:00 2001 From: Eugene Kovko <37694937+eukovko@users.noreply.github.com> Date: Mon, 5 Sep 2022 17:45:31 +0200 Subject: [PATCH] BAEL-4795: Static garbage collected fields (#12693) * BAEL-4795: Static garbage collected fields * BAEL-4795: Fix readAllBytes() --- .../baeldung/staticgc/CustomClassloader.java | 36 ++++++++++++++++++ .../GarbageCollectionExplicitExample.java | 28 ++++++++++++++ .../GarbageCollectionImplicitExample.java | 28 ++++++++++++++ .../GarbageCollectionNullExample.java | 28 ++++++++++++++ .../com/baeldung/staticgc/StaticField.java | 19 +++++++++ .../baeldung/staticgc/StaticFieldHolder.java | 7 ++++ .../GarbageCollectedInnerObject.class | Bin 0 -> 624 bytes .../GarbageCollectedStaticFieldHolder.class | Bin 0 -> 794 bytes .../GarbageCollectedStaticFieldHolder.java | 31 +++++++++++++++ 9 files changed, 177 insertions(+) create mode 100644 core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/CustomClassloader.java create mode 100644 core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/GarbageCollectionExplicitExample.java create mode 100644 core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/GarbageCollectionImplicitExample.java create mode 100644 core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/GarbageCollectionNullExample.java create mode 100644 core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/StaticField.java create mode 100644 core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/StaticFieldHolder.java create mode 100644 core-java-modules/core-java-jvm-2/src/main/resources/com/baeldung/classloader/GarbageCollectedInnerObject.class create mode 100644 core-java-modules/core-java-jvm-2/src/main/resources/com/baeldung/classloader/GarbageCollectedStaticFieldHolder.class create mode 100644 core-java-modules/core-java-jvm-2/src/main/resources/com/baeldung/classloader/GarbageCollectedStaticFieldHolder.java diff --git a/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/CustomClassloader.java b/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/CustomClassloader.java new file mode 100644 index 0000000000..23f3e88393 --- /dev/null +++ b/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/CustomClassloader.java @@ -0,0 +1,36 @@ +package com.baeldung.staticgc; + +import java.io.File; +import java.io.IOException; +import org.apache.commons.io.IOUtils; + +public class CustomClassloader extends ClassLoader { + + public static final String PREFIX = "com.baeldung.classloader"; + + public CustomClassloader(ClassLoader parent) { + super(parent); + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + if (name.startsWith(PREFIX)) { + return getClass(name); + } else { + return super.loadClass(name); + } + } + + private Class getClass(String name) { + String fileName = name.replace('.', File.separatorChar) + ".class"; + try { + byte[] byteArr = IOUtils.toByteArray(getClass().getClassLoader().getResourceAsStream(fileName)); + Class c = defineClass(name, byteArr, 0, byteArr.length); + resolveClass(c); + return c; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/GarbageCollectionExplicitExample.java b/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/GarbageCollectionExplicitExample.java new file mode 100644 index 0000000000..db572469ea --- /dev/null +++ b/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/GarbageCollectionExplicitExample.java @@ -0,0 +1,28 @@ +package com.baeldung.staticgc; + +public class GarbageCollectionExplicitExample { + + public static final String METHOD_NAME = "printValue"; + + public static void main(String[] args) throws InterruptedException { + loadClass(); + System.gc(); + Thread.sleep(1000); + } + + + /** + * The method loads a class and creates its instance. After the invocation of this method all the local variables go outside the scope. + */ + private static void loadClass() { + try { + final String className = "com.baeldung.classloader.GarbageCollectedStaticFieldHolder"; + CustomClassloader loader = new CustomClassloader(GarbageCollectionExplicitExample.class.getClassLoader()); + Class clazz = loader.loadClass(className); + Object instance = clazz.getConstructor().newInstance(); + clazz.getMethod(METHOD_NAME).invoke(instance); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/GarbageCollectionImplicitExample.java b/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/GarbageCollectionImplicitExample.java new file mode 100644 index 0000000000..fc2b9879e2 --- /dev/null +++ b/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/GarbageCollectionImplicitExample.java @@ -0,0 +1,28 @@ +package com.baeldung.staticgc; + +public class GarbageCollectionImplicitExample { + + public static final String METHOD_NAME = "printValue"; + +public static void main(String[] args) { + while (true) { + loadClass(); + } +} + + + /** + * The method loads a class and creates its instance. After the invocation of this method all the local variables go outside the scope. + */ + private static void loadClass() { + try { + final String className = "com.baeldung.classloader.GarbageCollectedStaticFieldHolder"; + CustomClassloader loader = new CustomClassloader(GarbageCollectionImplicitExample.class.getClassLoader()); + Class clazz = loader.loadClass(className); + Object instance = clazz.getConstructor().newInstance(); + clazz.getMethod(METHOD_NAME).invoke(instance); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/GarbageCollectionNullExample.java b/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/GarbageCollectionNullExample.java new file mode 100644 index 0000000000..44bdca90ec --- /dev/null +++ b/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/GarbageCollectionNullExample.java @@ -0,0 +1,28 @@ +package com.baeldung.staticgc; + +public class GarbageCollectionNullExample { + + public static final String METHOD_NAME = "printValue"; + +public static void main(String[] args) throws InterruptedException { + CustomClassloader loader; + Class clazz; + Object instance; + try { + final String className = "com.baeldung.classloader.GarbageCollectedStaticFieldHolder"; + loader = new CustomClassloader(GarbageCollectionNullExample.class.getClassLoader()); + clazz = loader.loadClass(className); + instance = clazz.getConstructor().newInstance(); + clazz.getMethod(METHOD_NAME).invoke(instance); + } catch (Exception e) { + throw new RuntimeException(e); + } + loader = null; + clazz = null; + instance = null; + System.gc(); + Thread.sleep(1000); +} + + +} diff --git a/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/StaticField.java b/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/StaticField.java new file mode 100644 index 0000000000..3900950ff2 --- /dev/null +++ b/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/StaticField.java @@ -0,0 +1,19 @@ +package com.baeldung.staticgc; + +public class StaticField { + + private final String value; + + public StaticField(final String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + @Override + protected void finalize() { + System.out.println("The object is garbage now"); + } +} diff --git a/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/StaticFieldHolder.java b/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/StaticFieldHolder.java new file mode 100644 index 0000000000..df7d794b3d --- /dev/null +++ b/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/staticgc/StaticFieldHolder.java @@ -0,0 +1,7 @@ +package com.baeldung.staticgc; + +public class StaticFieldHolder { + + private static StaticField staticField = new StaticField("Hello from static field"); + +} diff --git a/core-java-modules/core-java-jvm-2/src/main/resources/com/baeldung/classloader/GarbageCollectedInnerObject.class b/core-java-modules/core-java-jvm-2/src/main/resources/com/baeldung/classloader/GarbageCollectedInnerObject.class new file mode 100644 index 0000000000000000000000000000000000000000..074d566d026d1f1a697e252f2559fcb5a6c0798d GIT binary patch literal 624 zcmZWnNl)A`6#hJ0CTUnY3uSLW0?iCkbKyqC1qoV-7NkMkos1id92+H>R^?Z<6^q1y zAHa{Qcn$?bx!BKs?_2zy@BZH00@%i?hYG3=YCh^{FifBF?>tmoC*eVKD&m5n@lk47 zY%^4Q{bLtRxDGrYZ{Ra*#wHCTF4SmDh*~^t^H@gVUbClY`K`kl!Iv>Z_#?;X!tWPL`p`?n0$2~pwfhggewRwc)Ha@hhgsM zLW@kr5)mx$uaTyzPsgyny@ xCE6Kf>w^n8zn&nC@^Y3S?_pyru|@*6)cu2rR{ILwX9fGAK&;J@H=wwJm3wk&i3k7y literal 0 HcmV?d00001 diff --git a/core-java-modules/core-java-jvm-2/src/main/resources/com/baeldung/classloader/GarbageCollectedStaticFieldHolder.class b/core-java-modules/core-java-jvm-2/src/main/resources/com/baeldung/classloader/GarbageCollectedStaticFieldHolder.class new file mode 100644 index 0000000000000000000000000000000000000000..591ce17a32103d66fe66c886156a67c815cec1ab GIT binary patch literal 794 zcmbVK+fLg+5Ivg&oVZT8CA|T~w1vh+!Y>sMfOtWoR0=IpP^3PtoyA(T_99;@@mWxb zNUg*N@KIG~4TN5hK((dW+nF;nXXf(f_X_}9@N862wNP^~hH-|;BmR~9iYJl(IXDtw z&M>|y6Pa%@R6Ab3fjSx%YzL3v`~mNsWVwh5r3-RucS|Cv{ryxXc`r`|k2e~4j0p>q z4yG{8upa8z54cc+g5rgWXPMG`AX5JWPXiu_ZLJjLAO^jh=Q7-p1l`q&5Dc@?Uzm?c zBGQ|r*SZhp{>^X0Mhk5VPaHhOGluv7L&9K3BHt5PMinr$I^LBQrKlu?Od^W&0<#w8 z9L(b-!^|CGF<8e&I+c)`oqs93ejP5u%C1mKyN9WcUG83M;)XZExml^4duXIH)x9!} zrjWI5J)rC+x-t=;iZ~GI0S^@2*k#l{R|OsFo1wbyzTMMB8j2lhK+E?wXw{U2MQV73 z290P<%V}4oJxv