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