001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.lib.profiler.server.system;
042:
043: import java.lang.management.ClassLoadingMXBean;
044: import java.lang.management.ManagementFactory;
045:
046: /**
047: * Provides methods for dynamic bytecode redefinition and other class-related operations.
048: * A version for JDK 1.5
049: *
050: * @author Tomas Hurka
051: * @author Misha Dmitriev
052: */
053: public class Classes {
054: //~ Inner Classes ------------------------------------------------------------------------------------------------------------
055:
056: /** We convert all error codes or exceptions thrown by redefine calls into a single error message in
057: * this exception
058: */
059: public static class RedefineException extends Exception {
060: //~ Constructors ---------------------------------------------------------------------------------------------------------
061:
062: public RedefineException(String msg) {
063: super (msg);
064: }
065: }
066:
067: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
068:
069: private static ClassLoadingMXBean classLoadingBean;
070:
071: //~ Methods ------------------------------------------------------------------------------------------------------------------
072:
073: /**
074: * Returns all currently loaded *and linked* classes.
075: * On JDK 1.5, it returns just a Class[] array of all loaded classes
076: */
077: public static native Class[] getAllLoadedClasses();
078:
079: /**
080: * Returns the cached class file bytes for the given class. Currently
081: * agent (on JDK 1.5) caches these bytes only for classes loaded with custom classloaders (that is, not
082: * bootstrap (null) and not system classloader). If this method is called for a class loaded using bootstrap or
083: * system classloader, it just returns null.
084: */
085: public static native byte[] getCachedClassFileBytes(Class clazz);
086:
087: public static int getLoadedClassCount() {
088: return classLoadingBean.getLoadedClassCount();
089: }
090:
091: /** Object size for a given object */
092: public static native long getObjectSize(Object obj);
093:
094: public static native boolean setSleepTrackingEnabled(boolean value);
095:
096: public static native boolean setVMObjectAllocEnabled(boolean value);
097:
098: public static native boolean setWaitTrackingEnabled(boolean value);
099:
100: public static native void cacheLoadedClasses(
101: Class[] nonSystemClasses, int nonSystemIndex);
102:
103: /** Disables the above class load hook */
104: public static native void disableClassLoadHook();
105:
106: /**
107: * When the class load hook is enabled, it will call the ProfilerInterface.classLoadHook(Class) method every time
108: * a class is load and prepared.
109: */
110: public static native void enableClassLoadHook();
111:
112: /** Should be called at earliest possible time */
113: public static void initialize() {
114: classLoadingBean = ManagementFactory.getClassLoadingMXBean();
115: }
116:
117: /**
118: * This notifies the underlying native code about the fact that some classloader (we don't know which one since
119: * we use PhantomReferences for them) is unloaded. Thus the native code that could have cached the class file
120: * bytes for classes loaded with this loader, may release these bytes now. Really needed only in 1.5.
121: */
122: public static native void notifyAboutClassLoaderUnloading();
123:
124: /** RedefineClasses() as provided starting from JDK 1.5 */
125: public static void redefineClasses(Class[] classes,
126: byte[][] newClassFileBytes) throws RedefineException {
127: if (classes.length > newClassFileBytes.length) {
128: throw new RedefineException(
129: "Inconsistent input data: classes.length = "
130: + classes.length // NOI18N
131: + ", newClassFileBytes.length = "
132: + newClassFileBytes.length); // NOI18N
133: }
134:
135: for (int i = 0; i < classes.length; i++) {
136: if (classes[i] == null) {
137: throw new RedefineException(
138: "null input data: classes at " + i); // NOI18N
139: }
140:
141: if (newClassFileBytes[i] == null) {
142: throw new RedefineException(
143: "null input data: newClassFileBytes at " + i); // NOI18N
144: }
145: }
146:
147: int res = doRedefineClasses(classes, newClassFileBytes);
148:
149: if (res != 0) {
150: throw new RedefineException(
151: "Redefinition failed with error " + res
152: + "\n" // NOI18N
153: + "Check JVMTI documentation for this error code."); // NOI18N
154: }
155: }
156:
157: // ======================================== JDK 1.5 specific code ===============================================
158: private static native int doRedefineClasses(Class[] classes,
159: byte[][] newClassFileBytes);
160:
161: private static RedefineException newRedefineException(String msg,
162: Throwable origCause) {
163: msg = "Class redefinition error: " + msg
164: + "\nOriginal exception:\n" + origCause; // NOI18N
165:
166: return new RedefineException(msg);
167: }
168: }
|