Home | History | Annotate | Download | only in Events
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *
     15  *  See the License for the specific language governing permissions and
     16  *  limitations under the License.
     17  */
     18 
     19 /**
     20  * @author Aleksander V. Budniy
     21  */
     22 
     23 /**
     24  * Created on 25.11.2006
     25  */
     26 package org.apache.harmony.jpda.tests.jdwp.Events;
     27 
     28 import java.io.IOException;
     29 import java.io.InputStream;
     30 import java.net.URL;
     31 
     32 import org.apache.harmony.jpda.tests.framework.LogWriter;
     33 import org.apache.harmony.jpda.tests.framework.TestErrorException;
     34 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
     35 import org.apache.harmony.jpda.tests.share.SyncDebuggee;
     36 
     37 /**
     38  * Debuggee for ClassUnloadTest unit test.
     39  */
     40 public class ClassUnloadDebuggee extends SyncDebuggee {
     41 
     42 	public static final String TESTED_CLASS_NAME =
     43 		"org.apache.harmony.jpda.tests.jdwp.Events.ClassUnloadTestedClass";
     44 
     45 	public static final int ARRAY_SIZE_FOR_MEMORY_STRESS = 1000000;
     46 
     47 	public static volatile boolean classUnloaded = false;
     48 
     49 	public static void main(String[] args) {
     50         runDebuggee(ClassUnloadDebuggee.class);
     51     }
     52 
     53     public void run() {
     54         logWriter.println("--> ClassUnloadDebuggee started");
     55 
     56         // Test class prepare
     57         logWriter.println("--> Load and prepare tested class");
     58         CustomLoader loader = new CustomLoader(logWriter);
     59 
     60         Class cls = null;
     61         try {
     62 			cls = Class.forName(TESTED_CLASS_NAME, true, loader);
     63 	        logWriter.println("--> Tested class loaded: " + cls);
     64 		} catch (Exception e) {
     65 	        logWriter.println("--> Unable to load tested class: " + e);
     66 			throw new TestErrorException(e);
     67 		}
     68 
     69         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_READY);
     70         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
     71 
     72         logWriter.println("--> Erase references to loaded class and its class loader");
     73         classUnloaded = false;
     74         cls = null;
     75         loader = null;
     76 
     77         logWriter.println("--> Create memory stress and start gc");
     78         createMemoryStress(1000000, ARRAY_SIZE_FOR_MEMORY_STRESS);
     79 //        createMemoryStress(100000000, 1024);
     80         System.gc();
     81 
     82         String status = (classUnloaded ? "UNLOADED" : "LOADED");
     83         logWriter.println("--> Class status after memory stress: " + status);
     84         synchronizer.sendMessage(status);
     85         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
     86 
     87         logWriter.println("--> ClassUnloadDebuggee finished");
     88     }
     89 
     90     /*
     91      * Stress algorithm for eating memory.
     92      */
     93     protected void createMemoryStress(int arrayLength_0, int arrayLength_1) {
     94         Runtime currentRuntime = Runtime.getRuntime();
     95         long freeMemory = currentRuntime.freeMemory();
     96         logWriter.println
     97         ("--> Debuggee: createMemoryStress: freeMemory (bytes) before memory stress = " + freeMemory);
     98 
     99         long[][] longArrayForCreatingMemoryStress = null;
    100 
    101         int i = 0;
    102         try {
    103             longArrayForCreatingMemoryStress = new long[arrayLength_0][];
    104             for (; i < longArrayForCreatingMemoryStress.length; i++) {
    105                 longArrayForCreatingMemoryStress[i] = new long[arrayLength_1];
    106             }
    107             logWriter.println("--> Debuggee: createMemoryStress: NO OutOfMemoryError!!!");
    108         } catch ( OutOfMemoryError outOfMem ) {
    109             longArrayForCreatingMemoryStress = null;
    110             logWriter.println("--> Debuggee: createMemoryStress: OutOfMemoryError!!!");
    111         }
    112         freeMemory = currentRuntime.freeMemory();
    113         logWriter.println
    114         ("--> Debuggee: createMemoryStress: freeMemory after creating memory stress = " + freeMemory);
    115 
    116         longArrayForCreatingMemoryStress = null;
    117     }
    118 
    119     /**
    120      * More eager algorithm for eating memory.
    121      */
    122 /*
    123 	protected void createMemoryStress(int maxChunkSize, int minChunkSize) {
    124         Runtime currentRuntime = Runtime.getRuntime();
    125         long freeMemory = currentRuntime.freeMemory();
    126         logWriter.println
    127         ("--> Debuggee: createMemoryStress: freeMemory (bytes) before memory stress = " + freeMemory);
    128 
    129         LinkedList list = new LinkedList();
    130         int countOOM = 0;
    131 
    132         for (int chunkSize = maxChunkSize; chunkSize >= minChunkSize; chunkSize /= 2) {
    133         	try {
    134                 for (;;) {
    135                 	long[] chunk = new long[chunkSize];
    136                 	list.add(chunk);
    137                 }
    138             } catch (OutOfMemoryError outOfMem) {
    139                 countOOM++;
    140                 System.gc();
    141         	}
    142         }
    143 
    144         // enable to collect allocated memory
    145         list = null;
    146 
    147         freeMemory = currentRuntime.freeMemory();
    148         logWriter.println
    149         ("--> Debuggee: createMemoryStress: freeMemory after creating memory stress = " + freeMemory);
    150 
    151         logWriter.println
    152         ("--> Debuggee: createMemoryStress: OutOfMemoryError occured: " + countOOM);
    153     }
    154 */
    155 
    156     /**
    157      * Custom class loader to be used for tested class.
    158      * It will be collected and finalized when tested class is unloaded.
    159      */
    160     static class CustomLoader extends ClassLoader {
    161         private LogWriter logWriter;
    162 
    163         public CustomLoader(LogWriter writer) {
    164             this.logWriter = writer;
    165         }
    166 
    167         public Class<?> loadClass(String name) throws ClassNotFoundException {
    168             if (TESTED_CLASS_NAME.equals(name)) {
    169                 // load only tested class with this loader
    170                 return findClass(name);
    171             }
    172             return getParent().loadClass(name);
    173         }
    174 
    175         public Class<?> findClass(String name) throws ClassNotFoundException {
    176             try {
    177                 logWriter.println("-->> CustomClassLoader: Find class: " + name);
    178 	        	String res = name.replace('.', '/') + ".class";
    179 	            URL url = getResource(res);
    180                 logWriter.println("-->> CustomClassLoader: Found class file: " + res);
    181 	    		InputStream is = url.openStream();
    182 	            int size = 1024;
    183 	            byte bytes[] = new byte[size];
    184 	            int len = loadClassData(is, bytes, size);
    185                 logWriter.println("-->> CustomClassLoader: Loaded class bytes: " + len);
    186 	            Class cls = defineClass(name, bytes, 0, len);
    187                 logWriter.println("-->> CustomClassLoader: Defined class: " + cls);
    188 //	            resolveClass(cls);
    189 //                logWriter.println("-->> CustomClassLoader: Resolved class: " + cls);
    190 	            return cls;
    191         	} catch (Exception e) {
    192         		throw new ClassNotFoundException("Cannot load class: " + name, e);
    193         	}
    194         }
    195 
    196         private int loadClassData(InputStream in, byte[] raw, int size) throws IOException {
    197             int len = in.read(raw);
    198             if (len >= size)
    199                 throw new IOException("Class file is too big: " + len);
    200             in.close();
    201             return len;
    202         }
    203 
    204         protected void finalize() throws Throwable {
    205             logWriter.println("-->> CustomClassLoader: Class loader finalized => tested class UNLOADED");
    206             ClassUnloadDebuggee.classUnloaded = true;
    207        }
    208     }
    209 }
    210 
    211 /**
    212  * Internal class used in ClassUnloadTest
    213  */
    214 class ClassUnloadTestedClass {
    215 }
    216