|
Java example source code file (NoCallStackClassLoader.java)
The NoCallStackClassLoader.java Java example source code
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.remote.rmi;
import java.security.ProtectionDomain;
/**
<p>A class loader that only knows how to define a limited number
of classes, and load a limited number of other classes through
delegation to another loader. It is used to get around a problem
with Serialization, in particular as used by RMI (including
RMI/IIOP). The JMX Remote API defines exactly what class loader
must be used to deserialize arguments on the server, and return
values on the client. We communicate this class loader to RMI by
setting it as the context class loader. RMI uses the context
class loader to load classes as it deserializes, which is what we
want. However, before consulting the context class loader, it
looks up the call stack for a class with a non-null class loader,
and uses that if it finds one. So, in the standalone version of
javax.management.remote, if the class you're looking for is known
to the loader of jmxremote.jar (typically the system class loader)
then that loader will load it. This contradicts the class-loading
semantics required.
<p>We get around the problem by ensuring that the search up the
call stack will find a non-null class loader that doesn't load any
classes of interest, namely this one. So even though this loader
is indeed consulted during deserialization, it never finds the
class being deserialized. RMI then proceeds to use the context
class loader, as we require.
<p>This loader is constructed with the name and byte-code of one
or more classes that it defines, and a class-loader to which it
will delegate certain other classes required by that byte-code.
We construct the byte-code somewhat painstakingly, by compiling
the Java code directly, converting into a string, copying that
string into the class that needs this loader, and using the
stringToBytes method to convert it into the byte array. We
compile with -g:none because there's not much point in having
line-number information and the like in these directly-encoded
classes.
<p>The referencedClassNames should contain the names of all
classes that are referenced by the classes defined by this loader.
It is not necessary to include standard J2SE classes, however.
Here, a class is referenced if it is the superclass or a
superinterface of a defined class, or if it is the type of a
field, parameter, or return value. A class is not referenced if
it only appears in the throws clause of a method or constructor.
Of course, referencedClassNames should not contain any classes
that the user might want to deserialize, because the whole point
of this loader is that it does not find such classes.
*/
class NoCallStackClassLoader extends ClassLoader {
/** Simplified constructor when this loader only defines one class. */
public NoCallStackClassLoader(String className,
byte[] byteCode,
String[] referencedClassNames,
ClassLoader referencedClassLoader,
ProtectionDomain protectionDomain) {
this(new String[] {className}, new byte[][] {byteCode},
referencedClassNames, referencedClassLoader, protectionDomain);
}
public NoCallStackClassLoader(String[] classNames,
byte[][] byteCodes,
String[] referencedClassNames,
ClassLoader referencedClassLoader,
ProtectionDomain protectionDomain) {
super(null);
/* Validation. */
if (classNames == null || classNames.length == 0
|| byteCodes == null || classNames.length != byteCodes.length
|| referencedClassNames == null || protectionDomain == null)
throw new IllegalArgumentException();
for (int i = 0; i < classNames.length; i++) {
if (classNames[i] == null || byteCodes[i] == null)
throw new IllegalArgumentException();
}
for (int i = 0; i < referencedClassNames.length; i++) {
if (referencedClassNames[i] == null)
throw new IllegalArgumentException();
}
this.classNames = classNames;
this.byteCodes = byteCodes;
this.referencedClassNames = referencedClassNames;
this.referencedClassLoader = referencedClassLoader;
this.protectionDomain = protectionDomain;
}
/* This method is called at most once per name. Define the name
* if it is one of the classes whose byte code we have, or
* delegate the load if it is one of the referenced classes.
*/
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// Note: classNames is guaranteed by the constructor to be non-null.
for (int i = 0; i < classNames.length; i++) {
if (name.equals(classNames[i])) {
return defineClass(classNames[i], byteCodes[i], 0,
byteCodes[i].length, protectionDomain);
}
}
/* If the referencedClassLoader is null, it is the bootstrap
* class loader, and there's no point in delegating to it
* because it's already our parent class loader.
*/
if (referencedClassLoader != null) {
for (int i = 0; i < referencedClassNames.length; i++) {
if (name.equals(referencedClassNames[i]))
return referencedClassLoader.loadClass(name);
}
}
throw new ClassNotFoundException(name);
}
private final String[] classNames;
private final byte[][] byteCodes;
private final String[] referencedClassNames;
private final ClassLoader referencedClassLoader;
private final ProtectionDomain protectionDomain;
/**
* <p>Construct a
Other Java examples (source code examples)Here is a short list of links related to this Java NoCallStackClassLoader.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.