Guest User

Untitled

a guest
Jan 18th, 2017
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.25 KB | None | 0 0
  1. import java.io.IOException;
  2. import java.net.URLClassLoader;
  3. import java.nio.file.Files;
  4. import java.nio.file.Paths;
  5. import java.nio.file.Path;
  6.  
  7. /**
  8. * Example demonstrating a ClassLoader leak.
  9. *
  10. * <p>To see it in action, copy this file to a temp directory somewhere,
  11. * and then run:
  12. * <pre>{@code
  13. * javac ClassLoaderLeakExample.java
  14. * java -cp . ClassLoaderLeakExample
  15. * }</pre>
  16. *
  17. * <p>And watch the memory grow! On my system, using JDK 1.8.0_25, I start
  18. * getting OutofMemoryErrors within just a few seconds.
  19. *
  20. * <p>This class is implemented using some Java 8 features, mainly for
  21. * convenience in doing I/O. The same basic mechanism works in any version
  22. * of Java since 1.2.
  23. */
  24. public final class ClassLoaderLeakExample {
  25.  
  26. static volatile boolean running = true;
  27.  
  28. public static void main(String[] args) throws Exception {
  29. Thread thread = new LongRunningThread();
  30. try {
  31. thread.start();
  32. System.out.println("Running, press any key to stop.");
  33. System.in.read();
  34. } finally {
  35. running = false;
  36. thread.join();
  37. }
  38. }
  39.  
  40. /**
  41. * Implementation of the thread. It just calls {@link #loadAndDiscard()}
  42. * in a loop.
  43. */
  44. static final class LongRunningThread extends Thread {
  45. @Override public void run() {
  46. while(running) {
  47. try {
  48. loadAndDiscard();
  49. } catch (Throwable ex) {
  50. ex.printStackTrace();
  51. }
  52. try {
  53. Thread.sleep(100);
  54. } catch (InterruptedException ex) {
  55. System.out.println("Caught InterruptedException, shutting down.");
  56. running = false;
  57. }
  58. }
  59. }
  60. }
  61.  
  62. /**
  63. * A simple ClassLoader implementation that is only able to load one
  64. * class, the LoadedInChildClassLoader class. We have to jump through
  65. * some hoops here because we explicitly want to ensure we get a new
  66. * class each time (instead of reusing the class loaded by the system
  67. * class loader). If this child class were in a JAR file that wasn't
  68. * part of the system classpath, we wouldn't need this mechanism.
  69. */
  70. static final class ChildOnlyClassLoader extends ClassLoader {
  71. ChildOnlyClassLoader() {
  72. super(ClassLoaderLeakExample.class.getClassLoader());
  73. }
  74.  
  75. @Override protected Class<?> loadClass(String name, boolean resolve)
  76. throws ClassNotFoundException {
  77. if (!LoadedInChildClassLoader.class.getName().equals(name)) {
  78. return super.loadClass(name, resolve);
  79. }
  80. try {
  81. Path path = Paths.get(LoadedInChildClassLoader.class.getName()
  82. + ".class");
  83. byte[] classBytes = Files.readAllBytes(path);
  84. Class<?> c = defineClass(name, classBytes, 0, classBytes.length);
  85. if (resolve) {
  86. resolveClass(c);
  87. }
  88. return c;
  89. } catch (IOException ex) {
  90. throw new ClassNotFoundException("Could not load " + name, ex);
  91. }
  92. }
  93. }
  94.  
  95. /**
  96. * Helper method that constructs a new ClassLoader, loads a single class,
  97. * and then discards any reference to them. Theoretically, there should
  98. * be no GC impact, since no references can escape this method! But in
  99. * practice this will leak memory like a sieve.
  100. */
  101. static void loadAndDiscard() throws Exception {
  102. ClassLoader childClassLoader = new ChildOnlyClassLoader();
  103. Class<?> childClass = Class.forName(
  104. LoadedInChildClassLoader.class.getName(), true, childClassLoader);
  105. childClass.newInstance();
  106. // When this method returns, there will be no way to reference
  107. // childClassLoader or childClass at all, but they will still be
  108. // rooted for GC purposes!
  109. }
  110.  
  111. /**
  112. * An innocuous-looking class. Doesn't do anything interesting.
  113. */
  114. public static final class LoadedInChildClassLoader {
  115. // Grab a bunch of bytes. This isn't necessary for the leak, it just
  116. // makes the effect visible more quickly.
  117. // Note that we're really leaking these bytes, since we're effectively
  118. // creating a new instance of this static final field on each iteration!
  119. static final byte[] moreBytesToLeak = new byte[1024 * 1024 * 10];
  120.  
  121. private static final ThreadLocal<LoadedInChildClassLoader> threadLocal
  122. = new ThreadLocal<>();
  123.  
  124. public LoadedInChildClassLoader() {
  125. // Stash a reference to this class in the ThreadLocal
  126. threadLocal.set(this);
  127. }
  128. }
  129. }
Add Comment
Please, Sign In to add comment