15f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes/* 25f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * Licensed to the Apache Software Foundation (ASF) under one or more 35f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * contributor license agreements. See the NOTICE file distributed with 45f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * this work for additional information regarding copyright ownership. 55f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * The ASF licenses this file to You under the Apache License, Version 2.0 65f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * (the "License"); you may not use this file except in compliance with 75f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * the License. You may obtain a copy of the License at 85f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * 95f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 105f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * 115f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * Unless required by applicable law or agreed to in writing, software 125f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 135f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 145f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * 155f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * See the License for the specific language governing permissions and 165f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * limitations under the License. 175f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes */ 185f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 195f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes/** 205f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * @author Aleksander V. Budniy 215f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes */ 225f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 235f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes/** 245f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * Created on 25.11.2006 255f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes */ 265f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughespackage org.apache.harmony.jpda.tests.jdwp.Events; 275f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 285f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesimport java.io.IOException; 295f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesimport java.io.InputStream; 305f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesimport java.net.URL; 315f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 325f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesimport org.apache.harmony.jpda.tests.framework.LogWriter; 335f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesimport org.apache.harmony.jpda.tests.framework.TestErrorException; 345f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesimport org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer; 355f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesimport org.apache.harmony.jpda.tests.share.SyncDebuggee; 365f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 375f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes/** 385f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * Debuggee for ClassUnloadTest unit test. 395f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes */ 405f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughespublic class ClassUnloadDebuggee extends SyncDebuggee { 415f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 425f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes public static final String TESTED_CLASS_NAME = 435f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes "org.apache.harmony.jpda.tests.jdwp.Events.ClassUnloadTestedClass"; 445f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 455f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes public static final int ARRAY_SIZE_FOR_MEMORY_STRESS = 1000000; 465f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 475f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes public static volatile boolean classUnloaded = false; 485f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 495f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes public static void main(String[] args) { 505f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes runDebuggee(ClassUnloadDebuggee.class); 515f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 525f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 535f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes public void run() { 545f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println("--> ClassUnloadDebuggee started"); 555f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 565f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes // Test class prepare 575f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println("--> Load and prepare tested class"); 585f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes CustomLoader loader = new CustomLoader(logWriter); 595f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 605f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes Class cls = null; 615f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes try { 625f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes cls = Class.forName(TESTED_CLASS_NAME, true, loader); 635f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println("--> Tested class loaded: " + cls); 645f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } catch (Exception e) { 655f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println("--> Unable to load tested class: " + e); 665f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes throw new TestErrorException(e); 675f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 685f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 695f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_READY); 705f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 715f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 725f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println("--> Erase references to loaded class and its class loader"); 735f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes classUnloaded = false; 745f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes cls = null; 755f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes loader = null; 765f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 775f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println("--> Create memory stress and start gc"); 785f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes createMemoryStress(1000000, ARRAY_SIZE_FOR_MEMORY_STRESS); 795f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes// createMemoryStress(100000000, 1024); 805f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes System.gc(); 815f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 825f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes String status = (classUnloaded ? "UNLOADED" : "LOADED"); 835f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println("--> Class status after memory stress: " + status); 845f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes synchronizer.sendMessage(status); 855f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 865f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 875f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println("--> ClassUnloadDebuggee finished"); 885f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 895f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 905f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes /* 915f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * Stress algorithm for eating memory. 925f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes */ 935f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes protected void createMemoryStress(int arrayLength_0, int arrayLength_1) { 945f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes Runtime currentRuntime = Runtime.getRuntime(); 955f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes long freeMemory = currentRuntime.freeMemory(); 965f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println 975f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes ("--> Debuggee: createMemoryStress: freeMemory (bytes) before memory stress = " + freeMemory); 985f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 995f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes long[][] longArrayForCreatingMemoryStress = null; 1005f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 1015f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes int i = 0; 1025f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes try { 1035f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes longArrayForCreatingMemoryStress = new long[arrayLength_0][]; 1045f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes for (; i < longArrayForCreatingMemoryStress.length; i++) { 1055f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes longArrayForCreatingMemoryStress[i] = new long[arrayLength_1]; 1065f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 1075f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println("--> Debuggee: createMemoryStress: NO OutOfMemoryError!!!"); 1085f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } catch ( OutOfMemoryError outOfMem ) { 1095f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes longArrayForCreatingMemoryStress = null; 1105f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println("--> Debuggee: createMemoryStress: OutOfMemoryError!!!"); 1115f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 1125f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes freeMemory = currentRuntime.freeMemory(); 1135f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println 1145f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes ("--> Debuggee: createMemoryStress: freeMemory after creating memory stress = " + freeMemory); 1155f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 1165f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes longArrayForCreatingMemoryStress = null; 1175f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 1185f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 1195f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes /** 1205f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * More eager algorithm for eating memory. 1215f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes */ 1225f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes/* 1235f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes protected void createMemoryStress(int maxChunkSize, int minChunkSize) { 1245f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes Runtime currentRuntime = Runtime.getRuntime(); 1255f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes long freeMemory = currentRuntime.freeMemory(); 1265f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println 1275f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes ("--> Debuggee: createMemoryStress: freeMemory (bytes) before memory stress = " + freeMemory); 1285f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 1295f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes LinkedList list = new LinkedList(); 1305f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes int countOOM = 0; 1315f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 1325f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes for (int chunkSize = maxChunkSize; chunkSize >= minChunkSize; chunkSize /= 2) { 1335f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes try { 1345f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes for (;;) { 1355f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes long[] chunk = new long[chunkSize]; 1365f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes list.add(chunk); 1375f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 1385f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } catch (OutOfMemoryError outOfMem) { 1395f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes countOOM++; 1405f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes System.gc(); 1415f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 1425f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 1435f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 1445f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes // enable to collect allocated memory 1455f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes list = null; 1465f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 1475f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes freeMemory = currentRuntime.freeMemory(); 1485f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println 1495f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes ("--> Debuggee: createMemoryStress: freeMemory after creating memory stress = " + freeMemory); 1505f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 1515f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println 1525f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes ("--> Debuggee: createMemoryStress: OutOfMemoryError occured: " + countOOM); 1535f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 1545f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes*/ 1555f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 1565f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes /** 1575f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * Custom class loader to be used for tested class. 1585f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * It will be collected and finalized when tested class is unloaded. 1595f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes */ 1605f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes static class CustomLoader extends ClassLoader { 1615f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes private LogWriter logWriter; 1625f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 1635f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes public CustomLoader(LogWriter writer) { 1645f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes this.logWriter = writer; 1655f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 1665f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 1675f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes public Class<?> loadClass(String name) throws ClassNotFoundException { 1685f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes if (TESTED_CLASS_NAME.equals(name)) { 1695f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes // load only tested class with this loader 1705f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes return findClass(name); 1715f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 1725f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes return getParent().loadClass(name); 1735f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 1745f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 1755f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes public Class<?> findClass(String name) throws ClassNotFoundException { 1765f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes try { 1775f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println("-->> CustomClassLoader: Find class: " + name); 1785f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes String res = name.replace('.', '/') + ".class"; 1795f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes URL url = getResource(res); 1805f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println("-->> CustomClassLoader: Found class file: " + res); 1815f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes InputStream is = url.openStream(); 1825f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes int size = 1024; 1835f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes byte bytes[] = new byte[size]; 1845f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes int len = loadClassData(is, bytes, size); 1855f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println("-->> CustomClassLoader: Loaded class bytes: " + len); 1865f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes Class cls = defineClass(name, bytes, 0, len); 1875f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println("-->> CustomClassLoader: Defined class: " + cls); 1885f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes// resolveClass(cls); 1895f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes// logWriter.println("-->> CustomClassLoader: Resolved class: " + cls); 1905f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes return cls; 1915f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } catch (Exception e) { 1925f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes throw new ClassNotFoundException("Cannot load class: " + name, e); 1935f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 1945f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 1955f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 1965f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes private int loadClassData(InputStream in, byte[] raw, int size) throws IOException { 1975f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes int len = in.read(raw); 1985f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes if (len >= size) 1995f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes throw new IOException("Class file is too big: " + len); 2005f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes in.close(); 2015f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes return len; 2025f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 2035f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 2045f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes protected void finalize() throws Throwable { 2055f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes logWriter.println("-->> CustomClassLoader: Class loader finalized => tested class UNLOADED"); 2065f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes ClassUnloadDebuggee.classUnloaded = true; 2075f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 2085f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 2095f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes} 2105f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 2115f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes/** 2125f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * Internal class used in ClassUnloadTest 2135f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes */ 2145f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesclass ClassUnloadTestedClass { 2155f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes} 216