8327624: Remove VM implementation that bypass verification for core reflection

Reviewed-by: liach, dholmes, jrose, alanb, mli
This commit is contained in:
Mandy Chung 2024-10-22 18:14:37 +00:00
parent 28147dab07
commit d6eddcdaf9
28 changed files with 12 additions and 2817 deletions

@ -4076,26 +4076,6 @@ void ClassFileParser::check_super_class_access(const InstanceKlass* this_klass,
return;
}
// If the loader is not the boot loader then throw an exception if its
// superclass is in package jdk.internal.reflect and its loader is not a
// special reflection class loader
if (!this_klass->class_loader_data()->is_the_null_class_loader_data()) {
PackageEntry* super_package = super->package();
if (super_package != nullptr &&
super_package->name()->fast_compare(vmSymbols::jdk_internal_reflect()) == 0 &&
!java_lang_ClassLoader::is_reflection_class_loader(this_klass->class_loader())) {
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IllegalAccessError(),
"class %s loaded by %s cannot access jdk/internal/reflect superclass %s",
this_klass->external_name(),
this_klass->class_loader_data()->loader_name_and_id(),
super->external_name());
return;
}
}
Reflection::VerifyClassAccessResults vca_result =
Reflection::verify_class_access(this_klass, InstanceKlass::cast(super), false);
if (vca_result != Reflection::ACCESS_OK) {
@ -5106,7 +5086,7 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik,
// Set PackageEntry for this_klass
oop cl = ik->class_loader();
Handle clh = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(cl));
Handle clh = Handle(THREAD, cl);
ClassLoaderData* cld = ClassLoaderData::class_loader_data_or_null(clh());
ik->set_package(cld, nullptr, CHECK);

@ -644,8 +644,6 @@ Dictionary* ClassLoaderData::create_dictionary() {
int size;
if (_the_null_class_loader_data == nullptr) {
size = _boot_loader_dictionary_size;
} else if (class_loader()->is_a(vmClasses::reflect_DelegatingClassLoader_klass())) {
size = 1; // there's only one class in relection class loader and no initiated classes
} else if (is_system_class_loader_data()) {
size = _boot_loader_dictionary_size;
} else {
@ -815,8 +813,6 @@ ClassLoaderMetaspace* ClassLoaderData::metaspace_non_null() {
metaspace = new ClassLoaderMetaspace(_metaspace_lock, Metaspace::BootMetaspaceType);
} else if (has_class_mirror_holder()) {
metaspace = new ClassLoaderMetaspace(_metaspace_lock, Metaspace::ClassMirrorHolderMetaspaceType);
} else if (class_loader()->is_a(vmClasses::reflect_DelegatingClassLoader_klass())) {
metaspace = new ClassLoaderMetaspace(_metaspace_lock, Metaspace::ReflectionMetaspaceType);
} else {
metaspace = new ClassLoaderMetaspace(_metaspace_lock, Metaspace::StandardMetaspaceType);
}

@ -4763,9 +4763,6 @@ bool java_lang_ClassLoader::parallelCapable(oop class_loader) {
}
bool java_lang_ClassLoader::is_trusted_loader(oop loader) {
// Fix for 4474172; see evaluation for more details
loader = non_reflection_class_loader(loader);
oop cl = SystemDictionary::java_system_loader();
while(cl != nullptr) {
if (cl == loader) return true;
@ -4774,29 +4771,6 @@ bool java_lang_ClassLoader::is_trusted_loader(oop loader) {
return false;
}
// Return true if this is one of the class loaders associated with
// the generated bytecodes for serialization constructor returned
// by sun.reflect.ReflectionFactory::newConstructorForSerialization
bool java_lang_ClassLoader::is_reflection_class_loader(oop loader) {
if (loader != nullptr) {
Klass* delegating_cl_class = vmClasses::reflect_DelegatingClassLoader_klass();
// This might be null in non-1.4 JDKs
return (delegating_cl_class != nullptr && loader->is_a(delegating_cl_class));
}
return false;
}
oop java_lang_ClassLoader::non_reflection_class_loader(oop loader) {
// See whether this is one of the class loaders associated with
// the generated bytecodes for reflection, and if so, "magically"
// delegate to its parent to prevent class loading from occurring
// in places where applications using reflection didn't expect it.
if (is_reflection_class_loader(loader)) {
return parent(loader);
}
return loader;
}
oop java_lang_ClassLoader::unnamedModule(oop loader) {
assert(is_instance(loader), "loader must be oop");
return loader->obj_field(_unnamedModule_offset);

@ -1502,14 +1502,6 @@ class java_lang_ClassLoader : AllStatic {
static bool is_trusted_loader(oop loader);
// Return true if this is one of the class loaders associated with
// the generated bytecodes for serialization constructor returned
// by sun.reflect.ReflectionFactory::newConstructorForSerialization
static bool is_reflection_class_loader(oop loader);
// Fix for 4474172
static oop non_reflection_class_loader(oop loader);
// Testers
static bool is_subclass(Klass* klass) {
return klass->is_subclass_of(vmClasses::ClassLoader_klass());

@ -309,11 +309,6 @@ void Modules::define_module(Handle module, jboolean is_open, jstring version,
}
oop loader = java_lang_Module::loader(module());
// Make sure loader is not the jdk.internal.reflect.DelegatingClassLoader.
if (loader != java_lang_ClassLoader::non_reflection_class_loader(loader)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Class loader is an invalid delegating class loader");
}
Handle h_loader = Handle(THREAD, loader);
// define_module can be called during start-up, before the class loader's ClassLoaderData
// has been created. SystemDictionary::register_loader ensures creation, if needed.

@ -598,8 +598,6 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
HandleMark hm(THREAD);
// Fix for 4474172; see evaluation for more details
class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader()));
ClassLoaderData* loader_data = register_loader(class_loader);
Dictionary* dictionary = loader_data->dictionary();
@ -765,12 +763,7 @@ InstanceKlass* SystemDictionary::find_instance_klass(Thread* current,
Handle class_loader,
Handle protection_domain) {
// The result of this call should be consistent with the result
// of the call to resolve_instance_class_or_null().
// See evaluation 6790209 and 4474172 for more details.
oop class_loader_oop = java_lang_ClassLoader::non_reflection_class_loader(class_loader());
ClassLoaderData* loader_data = ClassLoaderData::class_loader_data_or_null(class_loader_oop);
ClassLoaderData* loader_data = ClassLoaderData::class_loader_data_or_null(class_loader());
if (loader_data == nullptr) {
// If the ClassLoaderData has not been setup,
// then the class loader has no entries in the dictionary.

@ -403,9 +403,6 @@ InstanceKlass* SystemDictionaryShared::find_or_load_shared_class(
if (SystemDictionary::is_system_class_loader(class_loader()) ||
SystemDictionary::is_platform_class_loader(class_loader())) {
// Fix for 4474172; see evaluation for more details
class_loader = Handle(
THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader()));
ClassLoaderData *loader_data = register_loader(class_loader);
Dictionary* dictionary = loader_data->dictionary();

@ -275,10 +275,6 @@ bool Verifier::verify(InstanceKlass* klass, bool should_verify_class, TRAPS) {
bool Verifier::is_eligible_for_verification(InstanceKlass* klass, bool should_verify_class) {
Symbol* name = klass->name();
Klass* refl_serialization_ctor_klass = vmClasses::reflect_SerializationConstructorAccessorImpl_klass();
bool is_reflect_accessor = refl_serialization_ctor_klass != nullptr &&
klass->is_subtype_of(refl_serialization_ctor_klass);
return (should_verify_for(klass->class_loader(), should_verify_class) &&
// return if the class is a bootstrapping class
@ -295,12 +291,7 @@ bool Verifier::is_eligible_for_verification(InstanceKlass* klass, bool should_ve
// Shared classes shouldn't have stackmaps either.
// However, bytecodes for shared old classes can be verified because
// they have not been rewritten.
!(klass->is_shared() && klass->is_rewritten()) &&
// As of the fix for 4486457 we disable verification for all of the
// dynamically-generated bytecodes associated with
// jdk/internal/reflect/SerializationConstructorAccessor.
(!is_reflect_accessor));
!(klass->is_shared() && klass->is_rewritten()));
}
Symbol* Verifier::inference_verify(

@ -107,11 +107,9 @@
do_klass(StackChunk_klass, jdk_internal_vm_StackChunk ) \
\
do_klass(reflect_MethodAccessorImpl_klass, reflect_MethodAccessorImpl ) \
do_klass(reflect_DelegatingClassLoader_klass, reflect_DelegatingClassLoader ) \
do_klass(reflect_ConstantPool_klass, reflect_ConstantPool ) \
do_klass(reflect_CallerSensitive_klass, reflect_CallerSensitive ) \
do_klass(reflect_DirectConstructorHandleAccessor_NativeAccessor_klass, reflect_DirectConstructorHandleAccessor_NativeAccessor) \
do_klass(reflect_SerializationConstructorAccessorImpl_klass, reflect_SerializationConstructorAccessorImpl ) \
\
/* support for dynamic typing */ \
do_klass(DirectMethodHandle_klass, java_lang_invoke_DirectMethodHandle ) \

@ -262,12 +262,10 @@ class SerializeClosure;
\
template(jdk_internal_reflect, "jdk/internal/reflect") \
template(reflect_MethodAccessorImpl, "jdk/internal/reflect/MethodAccessorImpl") \
template(reflect_DelegatingClassLoader, "jdk/internal/reflect/DelegatingClassLoader") \
template(reflect_Reflection, "jdk/internal/reflect/Reflection") \
template(reflect_CallerSensitive, "jdk/internal/reflect/CallerSensitive") \
template(reflect_CallerSensitive_signature, "Ljdk/internal/reflect/CallerSensitive;") \
template(reflect_DirectConstructorHandleAccessor_NativeAccessor, "jdk/internal/reflect/DirectConstructorHandleAccessor$NativeAccessor") \
template(reflect_SerializationConstructorAccessorImpl, "jdk/internal/reflect/SerializationConstructorAccessorImpl") \
template(clazz_name, "clazz") \
template(exceptionTypes_name, "exceptionTypes") \
template(modifiers_name, "modifiers") \

@ -1200,13 +1200,7 @@ Method* LinkResolver::linktime_resolve_special_method(const LinkInfo& link_info,
Klass* current_klass = link_info.current_klass();
if (current_klass != nullptr && resolved_klass->is_interface()) {
InstanceKlass* klass_to_check = InstanceKlass::cast(current_klass);
// Disable verification for the dynamically-generated reflection bytecodes
// for serialization constructor accessor.
bool is_reflect = klass_to_check->is_subclass_of(
vmClasses::reflect_SerializationConstructorAccessorImpl_klass());
if (!is_reflect &&
!klass_to_check->is_same_or_direct_interface(resolved_klass)) {
if (!klass_to_check->is_same_or_direct_interface(resolved_klass)) {
ResourceMark rm(THREAD);
stringStream ss;
ss.print("Interface method reference: '");

@ -3278,10 +3278,7 @@ JVM_ENTRY(jobject, JVM_LatestUserDefinedLoader(JNIEnv *env))
InstanceKlass* ik = vfst.method()->method_holder();
oop loader = ik->class_loader();
if (loader != nullptr && !SystemDictionary::is_platform_class_loader(loader)) {
// Skip reflection related frames
if (!ik->is_subclass_of(vmClasses::reflect_SerializationConstructorAccessorImpl_klass())) {
return JNIHandles::make_local(THREAD, loader);
}
return JNIHandles::make_local(THREAD, loader);
}
}
return nullptr;

@ -448,12 +448,6 @@ Reflection::VerifyClassAccessResults Reflection::verify_class_access(
is_same_class_package(current_class, new_class)) {
return ACCESS_OK;
}
// Allow all accesses from jdk/internal/reflect/SerializationConstructorAccessorImpl subclasses to
// succeed trivially.
if (vmClasses::reflect_SerializationConstructorAccessorImpl_klass_is_loaded() &&
current_class->is_subclass_of(vmClasses::reflect_SerializationConstructorAccessorImpl_klass())) {
return ACCESS_OK;
}
// module boundaries
if (new_class->is_public()) {
@ -658,12 +652,6 @@ bool Reflection::verify_member_access(const Klass* current_class,
}
}
// Allow all accesses from jdk/internal/reflect/SerializationConstructorAccessorImpl subclasses to
// succeed trivially.
if (current_class->is_subclass_of(vmClasses::reflect_SerializationConstructorAccessorImpl_klass())) {
return true;
}
// Check for special relaxations
return can_relax_access_check_for(current_class, member_class, classloader_only);
}

@ -1,722 +0,0 @@
/*
* Copyright (c) 2001, 2023, 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 jdk.internal.reflect;
import java.lang.reflect.*;
import jdk.internal.misc.Unsafe;
/** Shared functionality for all accessor generators */
class AccessorGenerator implements ClassFileConstants {
static final Unsafe unsafe = Unsafe.getUnsafe();
// Constants because there's no way to say "short integer constant",
// i.e., "1S"
protected static final short S0 = (short) 0;
protected static final short S1 = (short) 1;
protected static final short S2 = (short) 2;
protected static final short S3 = (short) 3;
protected static final short S4 = (short) 4;
protected static final short S5 = (short) 5;
protected static final short S6 = (short) 6;
// Instance variables for shared functionality
protected ClassFileAssembler asm;
protected int modifiers;
protected short thisClass;
protected short superClass;
protected short targetClass;
// Common constant pool entries to FieldAccessor and MethodAccessor
protected short throwableClass;
protected short classCastClass;
protected short nullPointerClass;
protected short illegalArgumentClass;
protected short invocationTargetClass;
protected short initIdx;
protected short initNameAndTypeIdx;
protected short initStringNameAndTypeIdx;
protected short nullPointerCtorIdx;
protected short illegalArgumentCtorIdx;
protected short illegalArgumentStringCtorIdx;
protected short invocationTargetCtorIdx;
protected short superCtorIdx;
protected short objectClass;
protected short toStringIdx;
protected short codeIdx;
protected short exceptionsIdx;
// Boxing
protected short valueOfIdx;
protected short booleanIdx;
protected short booleanBoxIdx;
protected short booleanUnboxIdx;
protected short byteIdx;
protected short byteBoxIdx;
protected short byteUnboxIdx;
protected short characterIdx;
protected short characterBoxIdx;
protected short characterUnboxIdx;
protected short doubleIdx;
protected short doubleBoxIdx;
protected short doubleUnboxIdx;
protected short floatIdx;
protected short floatBoxIdx;
protected short floatUnboxIdx;
protected short integerIdx;
protected short integerBoxIdx;
protected short integerUnboxIdx;
protected short longIdx;
protected short longBoxIdx;
protected short longUnboxIdx;
protected short shortIdx;
protected short shortBoxIdx;
protected short shortUnboxIdx;
protected final short NUM_COMMON_CPOOL_ENTRIES = (short) 30;
protected final short NUM_BOXING_CPOOL_ENTRIES = (short) 73;
// Requires that superClass has been set up
protected void emitCommonConstantPoolEntries() {
// + [UTF-8] "java/lang/Throwable"
// + [CONSTANT_Class_info] for above
// + [UTF-8] "java/lang/ClassCastException"
// + [CONSTANT_Class_info] for above
// + [UTF-8] "java/lang/NullPointerException"
// + [CONSTANT_Class_info] for above
// + [UTF-8] "java/lang/IllegalArgumentException"
// + [CONSTANT_Class_info] for above
// + [UTF-8] "java/lang/InvocationTargetException"
// + [CONSTANT_Class_info] for above
// + [UTF-8] "<init>"
// + [UTF-8] "()V"
// + [CONSTANT_NameAndType_info] for above
// + [CONSTANT_Methodref_info] for NullPointerException's constructor
// + [CONSTANT_Methodref_info] for IllegalArgumentException's constructor
// + [UTF-8] "(Ljava/lang/String;)V"
// + [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/String;)V"
// + [CONSTANT_Methodref_info] for IllegalArgumentException's constructor taking a String
// + [UTF-8] "(Ljava/lang/Throwable;)V"
// + [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/Throwable;)V"
// + [CONSTANT_Methodref_info] for InvocationTargetException's constructor
// + [CONSTANT_Methodref_info] for "super()"
// + [UTF-8] "java/lang/Object"
// + [CONSTANT_Class_info] for above
// + [UTF-8] "toString"
// + [UTF-8] "()Ljava/lang/String;"
// + [CONSTANT_NameAndType_info] for "toString()Ljava/lang/String;"
// + [CONSTANT_Methodref_info] for Object's toString method
// + [UTF-8] "Code"
// + [UTF-8] "Exceptions"
asm.emitConstantPoolUTF8("java/lang/Throwable");
asm.emitConstantPoolClass(asm.cpi());
throwableClass = asm.cpi();
asm.emitConstantPoolUTF8("java/lang/ClassCastException");
asm.emitConstantPoolClass(asm.cpi());
classCastClass = asm.cpi();
asm.emitConstantPoolUTF8("java/lang/NullPointerException");
asm.emitConstantPoolClass(asm.cpi());
nullPointerClass = asm.cpi();
asm.emitConstantPoolUTF8("java/lang/IllegalArgumentException");
asm.emitConstantPoolClass(asm.cpi());
illegalArgumentClass = asm.cpi();
asm.emitConstantPoolUTF8("java/lang/reflect/InvocationTargetException");
asm.emitConstantPoolClass(asm.cpi());
invocationTargetClass = asm.cpi();
asm.emitConstantPoolUTF8("<init>");
initIdx = asm.cpi();
asm.emitConstantPoolUTF8("()V");
asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
initNameAndTypeIdx = asm.cpi();
asm.emitConstantPoolMethodref(nullPointerClass, initNameAndTypeIdx);
nullPointerCtorIdx = asm.cpi();
asm.emitConstantPoolMethodref(illegalArgumentClass, initNameAndTypeIdx);
illegalArgumentCtorIdx = asm.cpi();
asm.emitConstantPoolUTF8("(Ljava/lang/String;)V");
asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
initStringNameAndTypeIdx = asm.cpi();
asm.emitConstantPoolMethodref(illegalArgumentClass, initStringNameAndTypeIdx);
illegalArgumentStringCtorIdx = asm.cpi();
asm.emitConstantPoolUTF8("(Ljava/lang/Throwable;)V");
asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
asm.emitConstantPoolMethodref(invocationTargetClass, asm.cpi());
invocationTargetCtorIdx = asm.cpi();
asm.emitConstantPoolMethodref(superClass, initNameAndTypeIdx);
superCtorIdx = asm.cpi();
asm.emitConstantPoolUTF8("java/lang/Object");
asm.emitConstantPoolClass(asm.cpi());
objectClass = asm.cpi();
asm.emitConstantPoolUTF8("toString");
asm.emitConstantPoolUTF8("()Ljava/lang/String;");
asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
asm.emitConstantPoolMethodref(objectClass, asm.cpi());
toStringIdx = asm.cpi();
asm.emitConstantPoolUTF8("Code");
codeIdx = asm.cpi();
asm.emitConstantPoolUTF8("Exceptions");
exceptionsIdx = asm.cpi();
}
/** Constant pool entries required to be able to box/unbox primitive
types. Note that we don't emit these if we don't need them. */
protected void emitBoxingContantPoolEntries() {
// * [UTF-8] "valueOf"
// * [UTF-8] "java/lang/Boolean"
// * [CONSTANT_Class_info] for above
// * [UTF-8] "(Z)Ljava/lang/Boolean;"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "booleanValue"
// * [UTF-8] "()Z"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "java/lang/Byte"
// * [CONSTANT_Class_info] for above
// * [UTF-8] "(B)Ljava/lang/Byte;"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "byteValue"
// * [UTF-8] "()B"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "java/lang/Character"
// * [CONSTANT_Class_info] for above
// * [UTF-8] "(C)Ljava/lang/Character;"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "charValue"
// * [UTF-8] "()C"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "java/lang/Double"
// * [CONSTANT_Class_info] for above
// * [UTF-8] "(D)Ljava/lang/Double;"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "doubleValue"
// * [UTF-8] "()D"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "java/lang/Float"
// * [CONSTANT_Class_info] for above
// * [UTF-8] "(F)Ljava/lang/Float;"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "floatValue"
// * [UTF-8] "()F"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "java/lang/Integer"
// * [CONSTANT_Class_info] for above
// * [UTF-8] "(I)Ljava/lang/Integer;"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "intValue"
// * [UTF-8] "()I"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "java/lang/Long"
// * [CONSTANT_Class_info] for above
// * [UTF-8] "(J)Ljava/lang/Long;"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "longValue"
// * [UTF-8] "()J"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "java/lang/Short"
// * [CONSTANT_Class_info] for above
// * [UTF-8] "(S)Ljava/lang/Short;"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "shortValue"
// * [UTF-8] "()S"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// valueOf-method name
asm.emitConstantPoolUTF8("valueOf");
valueOfIdx = asm.cpi();
// Boolean
asm.emitConstantPoolUTF8("java/lang/Boolean");
asm.emitConstantPoolClass(asm.cpi());
booleanIdx = asm.cpi();
asm.emitConstantPoolUTF8("(Z)Ljava/lang/Boolean;");
asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
booleanBoxIdx = asm.cpi();
asm.emitConstantPoolUTF8("booleanValue");
asm.emitConstantPoolUTF8("()Z");
asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
booleanUnboxIdx = asm.cpi();
// Byte
asm.emitConstantPoolUTF8("java/lang/Byte");
asm.emitConstantPoolClass(asm.cpi());
byteIdx = asm.cpi();
asm.emitConstantPoolUTF8("(B)Ljava/lang/Byte;");
asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
byteBoxIdx = asm.cpi();
asm.emitConstantPoolUTF8("byteValue");
asm.emitConstantPoolUTF8("()B");
asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
byteUnboxIdx = asm.cpi();
// Character
asm.emitConstantPoolUTF8("java/lang/Character");
asm.emitConstantPoolClass(asm.cpi());
characterIdx = asm.cpi();
asm.emitConstantPoolUTF8("(C)Ljava/lang/Character;");
asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
characterBoxIdx = asm.cpi();
asm.emitConstantPoolUTF8("charValue");
asm.emitConstantPoolUTF8("()C");
asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
characterUnboxIdx = asm.cpi();
// Double
asm.emitConstantPoolUTF8("java/lang/Double");
asm.emitConstantPoolClass(asm.cpi());
doubleIdx = asm.cpi();
asm.emitConstantPoolUTF8("(D)Ljava/lang/Double;");
asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
doubleBoxIdx = asm.cpi();
asm.emitConstantPoolUTF8("doubleValue");
asm.emitConstantPoolUTF8("()D");
asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
doubleUnboxIdx = asm.cpi();
// Float
asm.emitConstantPoolUTF8("java/lang/Float");
asm.emitConstantPoolClass(asm.cpi());
floatIdx = asm.cpi();
asm.emitConstantPoolUTF8("(F)Ljava/lang/Float;");
asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
floatBoxIdx = asm.cpi();
asm.emitConstantPoolUTF8("floatValue");
asm.emitConstantPoolUTF8("()F");
asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
floatUnboxIdx = asm.cpi();
// Integer
asm.emitConstantPoolUTF8("java/lang/Integer");
asm.emitConstantPoolClass(asm.cpi());
integerIdx = asm.cpi();
asm.emitConstantPoolUTF8("(I)Ljava/lang/Integer;");
asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
integerBoxIdx = asm.cpi();
asm.emitConstantPoolUTF8("intValue");
asm.emitConstantPoolUTF8("()I");
asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
integerUnboxIdx = asm.cpi();
// Long
asm.emitConstantPoolUTF8("java/lang/Long");
asm.emitConstantPoolClass(asm.cpi());
longIdx = asm.cpi();
asm.emitConstantPoolUTF8("(J)Ljava/lang/Long;");
asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
longBoxIdx = asm.cpi();
asm.emitConstantPoolUTF8("longValue");
asm.emitConstantPoolUTF8("()J");
asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
longUnboxIdx = asm.cpi();
// Short
asm.emitConstantPoolUTF8("java/lang/Short");
asm.emitConstantPoolClass(asm.cpi());
shortIdx = asm.cpi();
asm.emitConstantPoolUTF8("(S)Ljava/lang/Short;");
asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
shortBoxIdx = asm.cpi();
asm.emitConstantPoolUTF8("shortValue");
asm.emitConstantPoolUTF8("()S");
asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
shortUnboxIdx = asm.cpi();
}
// Necessary because of Java's annoying promotion rules
protected static short add(short s1, short s2) {
return (short) (s1 + s2);
}
protected static short sub(short s1, short s2) {
return (short) (s1 - s2);
}
protected boolean isStatic() {
return Modifier.isStatic(modifiers);
}
protected boolean isPrivate() {
return Modifier.isPrivate(modifiers);
}
/** Returns class name in "internal" form (i.e., '/' separators
instead of '.') */
protected static String getClassName
(Class<?> c, boolean addPrefixAndSuffixForNonPrimitiveTypes)
{
if (c.isPrimitive()) {
if (c == Boolean.TYPE) {
return "Z";
} else if (c == Byte.TYPE) {
return "B";
} else if (c == Character.TYPE) {
return "C";
} else if (c == Double.TYPE) {
return "D";
} else if (c == Float.TYPE) {
return "F";
} else if (c == Integer.TYPE) {
return "I";
} else if (c == Long.TYPE) {
return "J";
} else if (c == Short.TYPE) {
return "S";
} else if (c == Void.TYPE) {
return "V";
}
throw new InternalError("Should have found primitive type");
} else if (c.isArray()) {
return "[" + getClassName(c.getComponentType(), true);
} else {
if (addPrefixAndSuffixForNonPrimitiveTypes) {
return internalize("L" + c.getName() + ";");
} else {
return internalize(c.getName());
}
}
}
private static String internalize(String className) {
return className.replace('.', '/');
}
protected void emitConstructor() {
// Generate code into fresh code buffer
ClassFileAssembler cb = new ClassFileAssembler();
// 0 incoming arguments
cb.setMaxLocals(1);
cb.opc_aload_0();
cb.opc_invokespecial(superCtorIdx, 0, 0);
cb.opc_return();
// Emit method
emitMethod(initIdx, cb.getMaxLocals(), cb, null, null);
}
// The descriptor's index in the constant pool must be (1 +
// nameIdx). "numArgs" must indicate ALL arguments, including the
// implicit "this" argument; double and long arguments each count
// as 2 in this count. The code buffer must NOT contain the code
// length. The exception table may be null, but if non-null must
// NOT contain the exception table's length. The checked exception
// indices may be null.
protected void emitMethod(short nameIdx,
int numArgs,
ClassFileAssembler code,
ClassFileAssembler exceptionTable,
short[] checkedExceptionIndices)
{
int codeLen = code.getLength();
int excLen = 0;
if (exceptionTable != null) {
excLen = exceptionTable.getLength();
if ((excLen % 8) != 0) {
throw new IllegalArgumentException("Illegal exception table");
}
}
int attrLen = 12 + codeLen + excLen;
excLen = excLen / 8; // No-op if no exception table
asm.emitShort(ACC_PUBLIC);
asm.emitShort(nameIdx);
asm.emitShort(add(nameIdx, S1));
if (checkedExceptionIndices == null) {
// Code attribute only
asm.emitShort(S1);
} else {
// Code and Exceptions attributes
asm.emitShort(S2);
}
// Code attribute
asm.emitShort(codeIdx);
asm.emitInt(attrLen);
asm.emitShort(code.getMaxStack());
asm.emitShort((short) Math.max(numArgs, code.getMaxLocals()));
asm.emitInt(codeLen);
asm.append(code);
asm.emitShort((short) excLen);
if (exceptionTable != null) {
asm.append(exceptionTable);
}
asm.emitShort(S0); // No additional attributes for Code attribute
if (checkedExceptionIndices != null) {
// Exceptions attribute
asm.emitShort(exceptionsIdx);
asm.emitInt(2 + 2 * checkedExceptionIndices.length);
asm.emitShort((short) checkedExceptionIndices.length);
for (int i = 0; i < checkedExceptionIndices.length; i++) {
asm.emitShort(checkedExceptionIndices[i]);
}
}
}
protected short indexForPrimitiveType(Class<?> type) {
if (type == Boolean.TYPE) {
return booleanIdx;
} else if (type == Byte.TYPE) {
return byteIdx;
} else if (type == Character.TYPE) {
return characterIdx;
} else if (type == Double.TYPE) {
return doubleIdx;
} else if (type == Float.TYPE) {
return floatIdx;
} else if (type == Integer.TYPE) {
return integerIdx;
} else if (type == Long.TYPE) {
return longIdx;
} else if (type == Short.TYPE) {
return shortIdx;
}
throw new InternalError("Should have found primitive type");
}
protected short boxingMethodForPrimitiveType(Class<?> type) {
if (type == Boolean.TYPE) {
return booleanBoxIdx;
} else if (type == Byte.TYPE) {
return byteBoxIdx;
} else if (type == Character.TYPE) {
return characterBoxIdx;
} else if (type == Double.TYPE) {
return doubleBoxIdx;
} else if (type == Float.TYPE) {
return floatBoxIdx;
} else if (type == Integer.TYPE) {
return integerBoxIdx;
} else if (type == Long.TYPE) {
return longBoxIdx;
} else if (type == Short.TYPE) {
return shortBoxIdx;
}
throw new InternalError("Should have found primitive type");
}
/** Returns true for widening or identity conversions for primitive
types only */
protected static boolean canWidenTo(Class<?> type, Class<?> otherType) {
if (!type.isPrimitive()) {
return false;
}
// Widening conversions (from JVM spec):
// byte to short, int, long, float, or double
// short to int, long, float, or double
// char to int, long, float, or double
// int to long, float, or double
// long to float or double
// float to double
if (type == Boolean.TYPE) {
if (otherType == Boolean.TYPE) {
return true;
}
} else if (type == Byte.TYPE) {
if ( otherType == Byte.TYPE
|| otherType == Short.TYPE
|| otherType == Integer.TYPE
|| otherType == Long.TYPE
|| otherType == Float.TYPE
|| otherType == Double.TYPE) {
return true;
}
} else if (type == Short.TYPE) {
if ( otherType == Short.TYPE
|| otherType == Integer.TYPE
|| otherType == Long.TYPE
|| otherType == Float.TYPE
|| otherType == Double.TYPE) {
return true;
}
} else if (type == Character.TYPE) {
if ( otherType == Character.TYPE
|| otherType == Integer.TYPE
|| otherType == Long.TYPE
|| otherType == Float.TYPE
|| otherType == Double.TYPE) {
return true;
}
} else if (type == Integer.TYPE) {
if ( otherType == Integer.TYPE
|| otherType == Long.TYPE
|| otherType == Float.TYPE
|| otherType == Double.TYPE) {
return true;
}
} else if (type == Long.TYPE) {
if ( otherType == Long.TYPE
|| otherType == Float.TYPE
|| otherType == Double.TYPE) {
return true;
}
} else if (type == Float.TYPE) {
if ( otherType == Float.TYPE
|| otherType == Double.TYPE) {
return true;
}
} else if (type == Double.TYPE) {
if (otherType == Double.TYPE) {
return true;
}
}
return false;
}
/** Emits the widening bytecode for the given primitive conversion
(or none if the identity conversion). Requires that a primitive
conversion exists; i.e., canWidenTo must have already been
called and returned true. */
protected static void emitWideningBytecodeForPrimitiveConversion
(ClassFileAssembler cb,
Class<?> fromType,
Class<?> toType)
{
// Note that widening conversions for integral types (i.e., "b2s",
// "s2i") are no-ops since values on the Java stack are
// sign-extended.
// Widening conversions (from JVM spec):
// byte to short, int, long, float, or double
// short to int, long, float, or double
// char to int, long, float, or double
// int to long, float, or double
// long to float or double
// float to double
if ( fromType == Byte.TYPE
|| fromType == Short.TYPE
|| fromType == Character.TYPE
|| fromType == Integer.TYPE) {
if (toType == Long.TYPE) {
cb.opc_i2l();
} else if (toType == Float.TYPE) {
cb.opc_i2f();
} else if (toType == Double.TYPE) {
cb.opc_i2d();
}
} else if (fromType == Long.TYPE) {
if (toType == Float.TYPE) {
cb.opc_l2f();
} else if (toType == Double.TYPE) {
cb.opc_l2d();
}
} else if (fromType == Float.TYPE) {
if (toType == Double.TYPE) {
cb.opc_f2d();
}
}
// Otherwise, was identity or no-op conversion. Fall through.
}
protected short unboxingMethodForPrimitiveType(Class<?> primType) {
if (primType == Boolean.TYPE) {
return booleanUnboxIdx;
} else if (primType == Byte.TYPE) {
return byteUnboxIdx;
} else if (primType == Character.TYPE) {
return characterUnboxIdx;
} else if (primType == Short.TYPE) {
return shortUnboxIdx;
} else if (primType == Integer.TYPE) {
return integerUnboxIdx;
} else if (primType == Long.TYPE) {
return longUnboxIdx;
} else if (primType == Float.TYPE) {
return floatUnboxIdx;
} else if (primType == Double.TYPE) {
return doubleUnboxIdx;
}
throw new InternalError("Illegal primitive type " + primType.getName());
}
protected static final Class<?>[] primitiveTypes = new Class<?>[] {
Boolean.TYPE,
Byte.TYPE,
Character.TYPE,
Short.TYPE,
Integer.TYPE,
Long.TYPE,
Float.TYPE,
Double.TYPE
};
/** We don't consider "Void" to be a primitive type */
protected static boolean isPrimitive(Class<?> c) {
return (c.isPrimitive() && c != Void.TYPE);
}
protected int typeSizeInStackSlots(Class<?> c) {
if (c == Void.TYPE) {
return 0;
}
if (c == Long.TYPE || c == Double.TYPE) {
return 2;
}
return 1;
}
private ClassFileAssembler illegalArgumentCodeBuffer;
protected ClassFileAssembler illegalArgumentCodeBuffer() {
if (illegalArgumentCodeBuffer == null) {
illegalArgumentCodeBuffer = new ClassFileAssembler();
illegalArgumentCodeBuffer.opc_new(illegalArgumentClass);
illegalArgumentCodeBuffer.opc_dup();
illegalArgumentCodeBuffer.opc_invokespecial(illegalArgumentCtorIdx, 0, 0);
illegalArgumentCodeBuffer.opc_athrow();
}
return illegalArgumentCodeBuffer;
}
}

@ -1,37 +0,0 @@
/*
* Copyright (c) 2001, 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 jdk.internal.reflect;
/** A growable array of bytes. */
interface ByteVector {
public int getLength();
public byte get(int index);
public void put(int index, byte value);
public void add(byte value);
public void trim();
public byte[] getData();
}

@ -1,36 +0,0 @@
/*
* Copyright (c) 2001, 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 jdk.internal.reflect;
class ByteVectorFactory {
static ByteVector create() {
return new ByteVectorImpl();
}
static ByteVector create(int sz) {
return new ByteVectorImpl(sz);
}
}

@ -1,88 +0,0 @@
/*
* Copyright (c) 2001, 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 jdk.internal.reflect;
class ByteVectorImpl implements ByteVector {
private byte[] data;
private int pos;
public ByteVectorImpl() {
this(100);
}
public ByteVectorImpl(int sz) {
data = new byte[sz];
pos = -1;
}
public int getLength() {
return pos + 1;
}
public byte get(int index) {
if (index >= data.length) {
resize(index);
pos = index;
}
return data[index];
}
public void put(int index, byte value) {
if (index >= data.length) {
resize(index);
pos = index;
}
data[index] = value;
}
public void add(byte value) {
if (++pos >= data.length) {
resize(pos);
}
data[pos] = value;
}
public void trim() {
if (pos != data.length - 1) {
byte[] newData = new byte[pos + 1];
System.arraycopy(data, 0, newData, 0, pos + 1);
data = newData;
}
}
public byte[] getData() {
return data;
}
private void resize(int minSize) {
if (minSize <= 2 * data.length) {
minSize = 2 * data.length;
}
byte[] newData = new byte[minSize];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
}

@ -1,80 +0,0 @@
/*
* Copyright (c) 2001, 2023, 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 jdk.internal.reflect;
import java.security.AccessController;
import java.security.PrivilegedAction;
import jdk.internal.access.JavaLangAccess;
import jdk.internal.access.SharedSecrets;
/** Utility class which assists in calling defineClass() by
* creating a new class loader which delegates to the one needed in
* order for proper resolution of the given bytecodes to occur.
*
* This is only used to define SerializationConstructorAccessor.
*/
class ClassDefiner {
static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
/** <P> We define generated code into a new class loader which
delegates to the defining loader of the target class. It is
necessary for the VM to be able to resolve references to the
target class from the generated bytecodes, which could not occur
if the generated code was loaded into the bootstrap class
loader. </P>
<P> There are two primary reasons for creating a new loader
instead of defining these bytecodes directly into the defining
loader of the target class: first, it avoids any possible
security risk of having these bytecodes in the same loader.
Second, it allows the generated bytecodes to be unloaded earlier
than would otherwise be possible, decreasing run-time
footprint. </P>
*/
static Class<?> defineClass(String name, byte[] bytes, int off, int len,
final ClassLoader parentClassLoader)
{
@SuppressWarnings("removal")
ClassLoader newLoader = AccessController.doPrivileged(
new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return new DelegatingClassLoader(parentClassLoader);
}
});
return JLA.defineClass(newLoader, name, bytes, null, "__ClassDefiner__");
}
}
// NOTE: this class's name and presence are known to the virtual
// machine as of the fix for 4474172.
class DelegatingClassLoader extends ClassLoader {
DelegatingClassLoader(ClassLoader parent) {
super(parent);
}
}

@ -1,671 +0,0 @@
/*
* Copyright (c) 2001, 2004, 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 jdk.internal.reflect;
import sun.nio.cs.UTF_8;
class ClassFileAssembler implements ClassFileConstants {
private ByteVector vec;
private short cpIdx = 0;
public ClassFileAssembler() {
this(ByteVectorFactory.create());
}
public ClassFileAssembler(ByteVector vec) {
this.vec = vec;
}
public ByteVector getData() {
return vec;
}
/** Length in bytes */
public short getLength() {
return (short) vec.getLength();
}
public void emitMagicAndVersion() {
emitInt(0xCAFEBABE);
emitShort((short) 0);
emitShort((short) 49);
}
public void emitInt(int val) {
emitByte((byte) (val >> 24));
emitByte((byte) ((val >> 16) & 0xFF));
emitByte((byte) ((val >> 8) & 0xFF));
emitByte((byte) (val & 0xFF));
}
public void emitShort(short val) {
emitByte((byte) ((val >> 8) & 0xFF));
emitByte((byte) (val & 0xFF));
}
// Support for labels; package-private
void emitShort(short bci, short val) {
vec.put(bci, (byte) ((val >> 8) & 0xFF));
vec.put(bci + 1, (byte) (val & 0xFF));
}
public void emitByte(byte val) {
vec.add(val);
}
public void append(ClassFileAssembler asm) {
append(asm.vec);
}
public void append(ByteVector vec) {
for (int i = 0; i < vec.getLength(); i++) {
emitByte(vec.get(i));
}
}
/** Keeps track of the current (one-based) constant pool index;
incremented after emitting one of the following constant pool
entries. Can fetch the current constant pool index for use in
later entries. Index points at the last valid constant pool
entry; initially invalid. It is illegal to fetch the constant
pool index before emitting at least one constant pool entry. */
public short cpi() {
if (cpIdx == 0) {
throw new RuntimeException("Illegal use of ClassFileAssembler");
}
return cpIdx;
}
public void emitConstantPoolUTF8(String str) {
byte[] bytes = str.getBytes(UTF_8.INSTANCE);
emitByte(CONSTANT_Utf8);
emitShort((short) bytes.length);
for (int i = 0; i < bytes.length; i++) {
emitByte(bytes[i]);
}
cpIdx++;
}
public void emitConstantPoolClass(short index) {
emitByte(CONSTANT_Class);
emitShort(index);
cpIdx++;
}
public void emitConstantPoolNameAndType(short nameIndex, short typeIndex) {
emitByte(CONSTANT_NameAndType);
emitShort(nameIndex);
emitShort(typeIndex);
cpIdx++;
}
public void emitConstantPoolFieldref
(short classIndex, short nameAndTypeIndex)
{
emitByte(CONSTANT_Fieldref);
emitShort(classIndex);
emitShort(nameAndTypeIndex);
cpIdx++;
}
public void emitConstantPoolMethodref
(short classIndex, short nameAndTypeIndex)
{
emitByte(CONSTANT_Methodref);
emitShort(classIndex);
emitShort(nameAndTypeIndex);
cpIdx++;
}
public void emitConstantPoolInterfaceMethodref
(short classIndex, short nameAndTypeIndex)
{
emitByte(CONSTANT_InterfaceMethodref);
emitShort(classIndex);
emitShort(nameAndTypeIndex);
cpIdx++;
}
public void emitConstantPoolString(short utf8Index) {
emitByte(CONSTANT_String);
emitShort(utf8Index);
cpIdx++;
}
//----------------------------------------------------------------------
// Opcodes. Keeps track of maximum stack and locals. Make a new
// assembler for each piece of assembled code, then append the
// result to the previous assembler's class file.
//
private int stack = 0;
private int maxStack = 0;
private int maxLocals = 0;
private void incStack() {
setStack(stack + 1);
}
private void decStack() {
--stack;
}
public short getMaxStack() {
return (short) maxStack;
}
public short getMaxLocals() {
return (short) maxLocals;
}
/** It's necessary to be able to specify the number of arguments at
the beginning of the method (which translates to the initial
value of max locals) */
public void setMaxLocals(int maxLocals) {
this.maxLocals = maxLocals;
}
/** Needed to do flow control. Returns current stack depth. */
public int getStack() {
return stack;
}
/** Needed to do flow control. */
public void setStack(int value) {
stack = value;
if (stack > maxStack) {
maxStack = stack;
}
}
//-----------//
// Constants //
//-----------//
public void opc_aconst_null() {
emitByte(opc_aconst_null);
incStack();
}
public void opc_sipush(short constant) {
emitByte(opc_sipush);
emitShort(constant);
incStack();
}
public void opc_ldc(byte cpIdx) {
emitByte(opc_ldc);
emitByte(cpIdx);
incStack();
}
//---------------------------------//
// Local variable loads and stores //
//---------------------------------//
public void opc_iload_0() {
emitByte(opc_iload_0);
if (maxLocals < 1) maxLocals = 1;
incStack();
}
public void opc_iload_1() {
emitByte(opc_iload_1);
if (maxLocals < 2) maxLocals = 2;
incStack();
}
public void opc_iload_2() {
emitByte(opc_iload_2);
if (maxLocals < 3) maxLocals = 3;
incStack();
}
public void opc_iload_3() {
emitByte(opc_iload_3);
if (maxLocals < 4) maxLocals = 4;
incStack();
}
public void opc_lload_0() {
emitByte(opc_lload_0);
if (maxLocals < 2) maxLocals = 2;
incStack();
incStack();
}
public void opc_lload_1() {
emitByte(opc_lload_1);
if (maxLocals < 3) maxLocals = 3;
incStack();
incStack();
}
public void opc_lload_2() {
emitByte(opc_lload_2);
if (maxLocals < 4) maxLocals = 4;
incStack();
incStack();
}
public void opc_lload_3() {
emitByte(opc_lload_3);
if (maxLocals < 5) maxLocals = 5;
incStack();
incStack();
}
public void opc_fload_0() {
emitByte(opc_fload_0);
if (maxLocals < 1) maxLocals = 1;
incStack();
}
public void opc_fload_1() {
emitByte(opc_fload_1);
if (maxLocals < 2) maxLocals = 2;
incStack();
}
public void opc_fload_2() {
emitByte(opc_fload_2);
if (maxLocals < 3) maxLocals = 3;
incStack();
}
public void opc_fload_3() {
emitByte(opc_fload_3);
if (maxLocals < 4) maxLocals = 4;
incStack();
}
public void opc_dload_0() {
emitByte(opc_dload_0);
if (maxLocals < 2) maxLocals = 2;
incStack();
incStack();
}
public void opc_dload_1() {
emitByte(opc_dload_1);
if (maxLocals < 3) maxLocals = 3;
incStack();
incStack();
}
public void opc_dload_2() {
emitByte(opc_dload_2);
if (maxLocals < 4) maxLocals = 4;
incStack();
incStack();
}
public void opc_dload_3() {
emitByte(opc_dload_3);
if (maxLocals < 5) maxLocals = 5;
incStack();
incStack();
}
public void opc_aload_0() {
emitByte(opc_aload_0);
if (maxLocals < 1) maxLocals = 1;
incStack();
}
public void opc_aload_1() {
emitByte(opc_aload_1);
if (maxLocals < 2) maxLocals = 2;
incStack();
}
public void opc_aload_2() {
emitByte(opc_aload_2);
if (maxLocals < 3) maxLocals = 3;
incStack();
}
public void opc_aload_3() {
emitByte(opc_aload_3);
if (maxLocals < 4) maxLocals = 4;
incStack();
}
public void opc_aaload() {
emitByte(opc_aaload);
decStack();
}
public void opc_astore_0() {
emitByte(opc_astore_0);
if (maxLocals < 1) maxLocals = 1;
decStack();
}
public void opc_astore_1() {
emitByte(opc_astore_1);
if (maxLocals < 2) maxLocals = 2;
decStack();
}
public void opc_astore_2() {
emitByte(opc_astore_2);
if (maxLocals < 3) maxLocals = 3;
decStack();
}
public void opc_astore_3() {
emitByte(opc_astore_3);
if (maxLocals < 4) maxLocals = 4;
decStack();
}
//--------------------//
// Stack manipulation //
//--------------------//
public void opc_pop() {
emitByte(opc_pop);
decStack();
}
public void opc_dup() {
emitByte(opc_dup);
incStack();
}
public void opc_dup_x1() {
emitByte(opc_dup_x1);
incStack();
}
public void opc_swap() {
emitByte(opc_swap);
}
//---------------------------//
// Widening conversions only //
//---------------------------//
public void opc_i2l() {
emitByte(opc_i2l);
}
public void opc_i2f() {
emitByte(opc_i2f);
}
public void opc_i2d() {
emitByte(opc_i2d);
}
public void opc_l2f() {
emitByte(opc_l2f);
}
public void opc_l2d() {
emitByte(opc_l2d);
}
public void opc_f2d() {
emitByte(opc_f2d);
}
//--------------//
// Control flow //
//--------------//
public void opc_ifeq(short bciOffset) {
emitByte(opc_ifeq);
emitShort(bciOffset);
decStack();
}
/** Control flow with forward-reference BCI. Stack assumes
straight-through control flow. */
public void opc_ifeq(Label l) {
short instrBCI = getLength();
emitByte(opc_ifeq);
l.add(this, instrBCI, getLength(), getStack() - 1);
emitShort((short) -1); // Must be patched later
}
public void opc_if_icmpeq(short bciOffset) {
emitByte(opc_if_icmpeq);
emitShort(bciOffset);
setStack(getStack() - 2);
}
/** Control flow with forward-reference BCI. Stack assumes straight
control flow. */
public void opc_if_icmpeq(Label l) {
short instrBCI = getLength();
emitByte(opc_if_icmpeq);
l.add(this, instrBCI, getLength(), getStack() - 2);
emitShort((short) -1); // Must be patched later
}
public void opc_goto(short bciOffset) {
emitByte(opc_goto);
emitShort(bciOffset);
}
/** Control flow with forward-reference BCI. Stack assumes straight
control flow. */
public void opc_goto(Label l) {
short instrBCI = getLength();
emitByte(opc_goto);
l.add(this, instrBCI, getLength(), getStack());
emitShort((short) -1); // Must be patched later
}
public void opc_ifnull(short bciOffset) {
emitByte(opc_ifnull);
emitShort(bciOffset);
decStack();
}
/** Control flow with forward-reference BCI. Stack assumes straight
control flow. */
public void opc_ifnull(Label l) {
short instrBCI = getLength();
emitByte(opc_ifnull);
l.add(this, instrBCI, getLength(), getStack() - 1);
emitShort((short) -1); // Must be patched later
decStack();
}
public void opc_ifnonnull(short bciOffset) {
emitByte(opc_ifnonnull);
emitShort(bciOffset);
decStack();
}
/** Control flow with forward-reference BCI. Stack assumes straight
control flow. */
public void opc_ifnonnull(Label l) {
short instrBCI = getLength();
emitByte(opc_ifnonnull);
l.add(this, instrBCI, getLength(), getStack() - 1);
emitShort((short) -1); // Must be patched later
decStack();
}
//---------------------//
// Return instructions //
//---------------------//
public void opc_ireturn() {
emitByte(opc_ireturn);
setStack(0);
}
public void opc_lreturn() {
emitByte(opc_lreturn);
setStack(0);
}
public void opc_freturn() {
emitByte(opc_freturn);
setStack(0);
}
public void opc_dreturn() {
emitByte(opc_dreturn);
setStack(0);
}
public void opc_areturn() {
emitByte(opc_areturn);
setStack(0);
}
public void opc_return() {
emitByte(opc_return);
setStack(0);
}
//------------------//
// Field operations //
//------------------//
public void opc_getstatic(short fieldIndex, int fieldSizeInStackSlots) {
emitByte(opc_getstatic);
emitShort(fieldIndex);
setStack(getStack() + fieldSizeInStackSlots);
}
public void opc_putstatic(short fieldIndex, int fieldSizeInStackSlots) {
emitByte(opc_putstatic);
emitShort(fieldIndex);
setStack(getStack() - fieldSizeInStackSlots);
}
public void opc_getfield(short fieldIndex, int fieldSizeInStackSlots) {
emitByte(opc_getfield);
emitShort(fieldIndex);
setStack(getStack() + fieldSizeInStackSlots - 1);
}
public void opc_putfield(short fieldIndex, int fieldSizeInStackSlots) {
emitByte(opc_putfield);
emitShort(fieldIndex);
setStack(getStack() - fieldSizeInStackSlots - 1);
}
//--------------------//
// Method invocations //
//--------------------//
/** Long and double arguments and return types count as 2 arguments;
other values count as 1. */
public void opc_invokevirtual(short methodIndex,
int numArgs,
int numReturnValues)
{
emitByte(opc_invokevirtual);
emitShort(methodIndex);
setStack(getStack() - numArgs - 1 + numReturnValues);
}
/** Long and double arguments and return types count as 2 arguments;
other values count as 1. */
public void opc_invokespecial(short methodIndex,
int numArgs,
int numReturnValues)
{
emitByte(opc_invokespecial);
emitShort(methodIndex);
setStack(getStack() - numArgs - 1 + numReturnValues);
}
/** Long and double arguments and return types count as 2 arguments;
other values count as 1. */
public void opc_invokestatic(short methodIndex,
int numArgs,
int numReturnValues)
{
emitByte(opc_invokestatic);
emitShort(methodIndex);
setStack(getStack() - numArgs + numReturnValues);
}
/** Long and double arguments and return types count as 2 arguments;
other values count as 1. */
public void opc_invokeinterface(short methodIndex,
int numArgs,
byte count,
int numReturnValues)
{
emitByte(opc_invokeinterface);
emitShort(methodIndex);
emitByte(count);
emitByte((byte) 0);
setStack(getStack() - numArgs - 1 + numReturnValues);
}
//--------------//
// Array length //
//--------------//
public void opc_arraylength() {
emitByte(opc_arraylength);
}
//-----//
// New //
//-----//
public void opc_new(short classIndex) {
emitByte(opc_new);
emitShort(classIndex);
incStack();
}
//--------//
// Athrow //
//--------//
public void opc_athrow() {
emitByte(opc_athrow);
setStack(1);
}
//--------------------------//
// Checkcast and instanceof //
//--------------------------//
/** Assumes the checkcast succeeds */
public void opc_checkcast(short classIndex) {
emitByte(opc_checkcast);
emitShort(classIndex);
}
public void opc_instanceof(short classIndex) {
emitByte(opc_instanceof);
emitShort(classIndex);
}
}

@ -1,140 +0,0 @@
/*
* Copyright (c) 2001, 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 jdk.internal.reflect;
/** Minimal set of class file constants for assembly of field and
method accessors. */
interface ClassFileConstants {
// Constants
public static final byte opc_aconst_null = (byte) 0x1;
public static final byte opc_sipush = (byte) 0x11;
public static final byte opc_ldc = (byte) 0x12;
// Local variable loads and stores
public static final byte opc_iload_0 = (byte) 0x1a;
public static final byte opc_iload_1 = (byte) 0x1b;
public static final byte opc_iload_2 = (byte) 0x1c;
public static final byte opc_iload_3 = (byte) 0x1d;
public static final byte opc_lload_0 = (byte) 0x1e;
public static final byte opc_lload_1 = (byte) 0x1f;
public static final byte opc_lload_2 = (byte) 0x20;
public static final byte opc_lload_3 = (byte) 0x21;
public static final byte opc_fload_0 = (byte) 0x22;
public static final byte opc_fload_1 = (byte) 0x23;
public static final byte opc_fload_2 = (byte) 0x24;
public static final byte opc_fload_3 = (byte) 0x25;
public static final byte opc_dload_0 = (byte) 0x26;
public static final byte opc_dload_1 = (byte) 0x27;
public static final byte opc_dload_2 = (byte) 0x28;
public static final byte opc_dload_3 = (byte) 0x29;
public static final byte opc_aload_0 = (byte) 0x2a;
public static final byte opc_aload_1 = (byte) 0x2b;
public static final byte opc_aload_2 = (byte) 0x2c;
public static final byte opc_aload_3 = (byte) 0x2d;
public static final byte opc_aaload = (byte) 0x32;
public static final byte opc_astore_0 = (byte) 0x4b;
public static final byte opc_astore_1 = (byte) 0x4c;
public static final byte opc_astore_2 = (byte) 0x4d;
public static final byte opc_astore_3 = (byte) 0x4e;
// Stack manipulation
public static final byte opc_pop = (byte) 0x57;
public static final byte opc_dup = (byte) 0x59;
public static final byte opc_dup_x1 = (byte) 0x5a;
public static final byte opc_swap = (byte) 0x5f;
// Conversions
public static final byte opc_i2l = (byte) 0x85;
public static final byte opc_i2f = (byte) 0x86;
public static final byte opc_i2d = (byte) 0x87;
public static final byte opc_l2i = (byte) 0x88;
public static final byte opc_l2f = (byte) 0x89;
public static final byte opc_l2d = (byte) 0x8a;
public static final byte opc_f2i = (byte) 0x8b;
public static final byte opc_f2l = (byte) 0x8c;
public static final byte opc_f2d = (byte) 0x8d;
public static final byte opc_d2i = (byte) 0x8e;
public static final byte opc_d2l = (byte) 0x8f;
public static final byte opc_d2f = (byte) 0x90;
public static final byte opc_i2b = (byte) 0x91;
public static final byte opc_i2c = (byte) 0x92;
public static final byte opc_i2s = (byte) 0x93;
// Control flow
public static final byte opc_ifeq = (byte) 0x99;
public static final byte opc_if_icmpeq = (byte) 0x9f;
public static final byte opc_goto = (byte) 0xa7;
// Return instructions
public static final byte opc_ireturn = (byte) 0xac;
public static final byte opc_lreturn = (byte) 0xad;
public static final byte opc_freturn = (byte) 0xae;
public static final byte opc_dreturn = (byte) 0xaf;
public static final byte opc_areturn = (byte) 0xb0;
public static final byte opc_return = (byte) 0xb1;
// Field operations
public static final byte opc_getstatic = (byte) 0xb2;
public static final byte opc_putstatic = (byte) 0xb3;
public static final byte opc_getfield = (byte) 0xb4;
public static final byte opc_putfield = (byte) 0xb5;
// Method invocations
public static final byte opc_invokevirtual = (byte) 0xb6;
public static final byte opc_invokespecial = (byte) 0xb7;
public static final byte opc_invokestatic = (byte) 0xb8;
public static final byte opc_invokeinterface = (byte) 0xb9;
// Array length
public static final byte opc_arraylength = (byte) 0xbe;
// New
public static final byte opc_new = (byte) 0xbb;
// Athrow
public static final byte opc_athrow = (byte) 0xbf;
// Checkcast and instanceof
public static final byte opc_checkcast = (byte) 0xc0;
public static final byte opc_instanceof = (byte) 0xc1;
// Ifnull and ifnonnull
public static final byte opc_ifnull = (byte) 0xc6;
public static final byte opc_ifnonnull = (byte) 0xc7;
// Constant pool tags
public static final byte CONSTANT_Class = (byte) 7;
public static final byte CONSTANT_Fieldref = (byte) 9;
public static final byte CONSTANT_Methodref = (byte) 10;
public static final byte CONSTANT_InterfaceMethodref = (byte) 11;
public static final byte CONSTANT_NameAndType = (byte) 12;
public static final byte CONSTANT_String = (byte) 8;
public static final byte CONSTANT_Utf8 = (byte) 1;
// Access flags
public static final short ACC_PUBLIC = (short) 0x0001;
}

@ -27,12 +27,7 @@ package jdk.internal.reflect;
import java.lang.reflect.InvocationTargetException;
/** Package-private implementation of the ConstructorAccessor
interface which has access to all classes and all fields,
regardless of language restrictions. See MagicAccessorImpl. */
abstract class ConstructorAccessorImpl extends MagicAccessorImpl
implements ConstructorAccessor {
abstract class ConstructorAccessorImpl implements ConstructorAccessor {
/** Matches specification in {@link java.lang.reflect.Constructor} */
public abstract Object newInstance(Object[] args)
throws InstantiationException,

@ -28,12 +28,7 @@ package jdk.internal.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/** Package-private implementation of the FieldAccessor interface
which has access to all classes and all fields, regardless of
language restrictions. See MagicAccessorImpl. */
abstract class FieldAccessorImpl extends MagicAccessorImpl
implements FieldAccessor {
abstract class FieldAccessorImpl implements FieldAccessor {
protected final Field field;
FieldAccessorImpl(Field field) {

@ -1,76 +0,0 @@
/*
* Copyright (c) 2001, 2011, 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 jdk.internal.reflect;
import java.util.List;
import java.util.ArrayList;
/** Allows forward references in bytecode streams emitted by
ClassFileAssembler. Assumes that the start of the method body is
the first byte in the assembler's buffer. May be used at more than
one branch site. */
class Label {
static class PatchInfo {
PatchInfo(ClassFileAssembler asm,
short instrBCI,
short patchBCI,
int stackDepth)
{
this.asm = asm;
this.instrBCI = instrBCI;
this.patchBCI = patchBCI;
this.stackDepth = stackDepth;
}
// This won't work for more than one assembler anyway, so this is
// unnecessary
final ClassFileAssembler asm;
final short instrBCI;
final short patchBCI;
final int stackDepth;
}
private final List<PatchInfo> patches = new ArrayList<>();
public Label() {
}
void add(ClassFileAssembler asm,
short instrBCI,
short patchBCI,
int stackDepth)
{
patches.add(new PatchInfo(asm, instrBCI, patchBCI, stackDepth));
}
public void bind() {
for (PatchInfo patch : patches){
short curBCI = patch.asm.getLength();
short offset = (short) (curBCI - patch.instrBCI);
patch.asm.emitShort(patch.patchBCI, offset);
patch.asm.setStack(patch.stackDepth);
}
}
}

@ -1,47 +0,0 @@
/*
* Copyright (c) 2001, 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 jdk.internal.reflect;
/** <P> MagicAccessorImpl (named for parity with FieldAccessorImpl and
others, not because it actually implements an interface) is a
marker class in the hierarchy. All subclasses of this class are
"magically" granted access by the VM to otherwise inaccessible
fields and methods of other classes. It is used to hold the code
for dynamically-generated FieldAccessorImpl and MethodAccessorImpl
subclasses. (Use of the word "unsafe" was avoided in this class's
name to avoid confusion with {@link jdk.internal.misc.Unsafe}.) </P>
<P> The bug fix for 4486457 also necessitated disabling
verification for this class and all subclasses, as opposed to just
SerializationConstructorAccessorImpl and subclasses, to avoid
having to indicate to the VM which of these dynamically-generated
stub classes were known to be able to pass the verifier. </P>
<P> Do not change the name of this class without also changing the
VM's code. </P> */
class MagicAccessorImpl {
}

@ -27,11 +27,7 @@ package jdk.internal.reflect;
import java.lang.reflect.InvocationTargetException;
/** <P> Package-private implementation of the MethodAccessor interface
which has access to all classes and all fields, regardless of
language restrictions. See MagicAccessor. </P>
<P> This class is known to the VM; do not change its name without
/** <P> This class is known to the VM; do not change its name without
also changing the VM's code. </P>
<P> NOTE: ALL methods of subclasses are skipped during security
@ -40,8 +36,7 @@ import java.lang.reflect.InvocationTargetException;
methods for java.lang.reflect.Method.invoke(). </P>
*/
abstract class MethodAccessorImpl extends MagicAccessorImpl
implements MethodAccessor {
abstract class MethodAccessorImpl implements MethodAccessor {
/** Matches specification in {@link java.lang.reflect.Method} */
public abstract Object invoke(Object obj, Object[] args)
throws IllegalArgumentException, InvocationTargetException;

@ -334,16 +334,8 @@ public class ReflectionFactory {
private final Constructor<?> generateConstructor(Class<?> cl,
Constructor<?> constructorToCall) {
ConstructorAccessor acc;
if (useOldSerializableConstructor()) {
acc = new SerializationConstructorAccessorGenerator().
generateSerializationConstructor(cl,
constructorToCall.getParameterTypes(),
constructorToCall.getModifiers(),
constructorToCall.getDeclaringClass());
} else {
acc = MethodHandleAccessorFactory.newSerializableConstructorAccessor(cl, constructorToCall);
}
ConstructorAccessor acc = MethodHandleAccessorFactory
.newSerializableConstructorAccessor(cl, constructorToCall);
// Unlike other root constructors, this constructor is not copied for mutation
// but directly mutated, as it is not cached. To cache this constructor,
// setAccessible call must be done on a copy and return that copy instead.
@ -507,10 +499,6 @@ public class ReflectionFactory {
return config().useNativeAccessorOnly;
}
static boolean useOldSerializableConstructor() {
return config().useOldSerializableConstructor;
}
private static boolean disableSerialConstructorChecks() {
return config().disableSerialConstructorChecks;
}
@ -527,7 +515,6 @@ public class ReflectionFactory {
private static @Stable Config config;
private static final Config DEFAULT_CONFIG = new Config(false, // useNativeAccessorOnly
false, // useOldSerializeableConstructor
false); // disableSerialConstructorChecks
/**
@ -542,7 +529,6 @@ public class ReflectionFactory {
* is to override them.
*/
private record Config(boolean useNativeAccessorOnly,
boolean useOldSerializableConstructor,
boolean disableSerialConstructorChecks) {
}
@ -566,12 +552,10 @@ public class ReflectionFactory {
Properties props = GetPropertyAction.privilegedGetProperties();
boolean useNativeAccessorOnly =
"true".equals(props.getProperty("jdk.reflect.useNativeAccessorOnly"));
boolean useOldSerializableConstructor =
"true".equals(props.getProperty("jdk.reflect.useOldSerializableConstructor"));
boolean disableSerialConstructorChecks =
"true".equals(props.getProperty("jdk.disableSerialConstructorChecks"));
return new Config(useNativeAccessorOnly, useOldSerializableConstructor, disableSerialConstructorChecks);
return new Config(useNativeAccessorOnly, disableSerialConstructorChecks);
}
/**

@ -1,725 +0,0 @@
/*
* Copyright (c) 2001, 2023, 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 jdk.internal.reflect;
import java.security.AccessController;
import java.security.PrivilegedAction;
/** Generator for jdk.internal.reflect.SerializationConstructorAccessorImpl
objects using bytecodes to implement a constructor for serialization
returned by ReflectionFactory::newConstructorForSerialization. */
class SerializationConstructorAccessorGenerator extends AccessorGenerator {
private static final short NUM_BASE_CPOOL_ENTRIES = (short) 12;
// One for invoke() plus one for constructor
private static final short NUM_METHODS = (short) 2;
// Only used if forSerialization is true
private static final short NUM_SERIALIZATION_CPOOL_ENTRIES = (short) 2;
private static volatile int methodSymnum;
private static volatile int constructorSymnum;
private static volatile int serializationConstructorSymnum;
private Class<?> declaringClass;
private Class<?>[] parameterTypes;
private Class<?> returnType;
private boolean isConstructor;
private boolean forSerialization;
private short targetMethodRef;
private short invokeIdx;
private short invokeDescriptorIdx;
// Constant pool index of CONSTANT_Class_info for first
// non-primitive parameter type. Should be incremented by 2.
private short nonPrimitiveParametersBaseIdx;
SerializationConstructorAccessorGenerator() {
}
/** This routine is not thread-safe */
public SerializationConstructorAccessorImpl
generateSerializationConstructor(Class<?> declaringClass,
Class<?>[] parameterTypes,
int modifiers,
Class<?> targetConstructorClass)
{
return (SerializationConstructorAccessorImpl)
generate(declaringClass,
"<init>",
parameterTypes,
Void.TYPE,
modifiers,
true,
true,
targetConstructorClass);
}
/** This routine is not thread-safe */
@SuppressWarnings("removal")
private MagicAccessorImpl generate(final Class<?> declaringClass,
String name,
Class<?>[] parameterTypes,
Class<?> returnType,
int modifiers,
boolean isConstructor,
boolean forSerialization,
Class<?> serializationTargetClass)
{
ByteVector vec = ByteVectorFactory.create();
asm = new ClassFileAssembler(vec);
this.declaringClass = declaringClass;
this.parameterTypes = parameterTypes;
this.returnType = returnType;
this.modifiers = modifiers;
this.isConstructor = isConstructor;
this.forSerialization = forSerialization;
asm.emitMagicAndVersion();
// Constant pool entries:
// ( * = Boxing information: optional)
// (+ = Shared entries provided by AccessorGenerator)
// (^ = Only present if generating SerializationConstructorAccessor)
// [UTF-8] [This class's name]
// [CONSTANT_Class_info] for above
// [UTF-8] "jdk/internal/reflect/{MethodAccessorImpl,ConstructorAccessorImpl,SerializationConstructorAccessorImpl}"
// [CONSTANT_Class_info] for above
// [UTF-8] [Target class's name]
// [CONSTANT_Class_info] for above
// ^ [UTF-8] [Serialization: Class's name in which to invoke constructor]
// ^ [CONSTANT_Class_info] for above
// [UTF-8] target method or constructor name
// [UTF-8] target method or constructor signature
// [CONSTANT_NameAndType_info] for above
// [CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info] for target method
// [UTF-8] "invoke" or "newInstance"
// [UTF-8] invoke or newInstance descriptor
// [UTF-8] descriptor for type of non-primitive parameter 1
// [CONSTANT_Class_info] for type of non-primitive parameter 1
// ...
// [UTF-8] descriptor for type of non-primitive parameter n
// [CONSTANT_Class_info] for type of non-primitive parameter n
// + [UTF-8] "java/lang/Exception"
// + [CONSTANT_Class_info] for above
// + [UTF-8] "java/lang/ClassCastException"
// + [CONSTANT_Class_info] for above
// + [UTF-8] "java/lang/NullPointerException"
// + [CONSTANT_Class_info] for above
// + [UTF-8] "java/lang/IllegalArgumentException"
// + [CONSTANT_Class_info] for above
// + [UTF-8] "java/lang/InvocationTargetException"
// + [CONSTANT_Class_info] for above
// + [UTF-8] "<init>"
// + [UTF-8] "()V"
// + [CONSTANT_NameAndType_info] for above
// + [CONSTANT_Methodref_info] for NullPointerException's constructor
// + [CONSTANT_Methodref_info] for IllegalArgumentException's constructor
// + [UTF-8] "(Ljava/lang/String;)V"
// + [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/String;)V"
// + [CONSTANT_Methodref_info] for IllegalArgumentException's constructor taking a String
// + [UTF-8] "(Ljava/lang/Throwable;)V"
// + [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/Throwable;)V"
// + [CONSTANT_Methodref_info] for InvocationTargetException's constructor
// + [CONSTANT_Methodref_info] for "super()"
// + [UTF-8] "java/lang/Object"
// + [CONSTANT_Class_info] for above
// + [UTF-8] "toString"
// + [UTF-8] "()Ljava/lang/String;"
// + [CONSTANT_NameAndType_info] for "toString()Ljava/lang/String;"
// + [CONSTANT_Methodref_info] for Object's toString method
// + [UTF-8] "Code"
// + [UTF-8] "Exceptions"
// * [UTF-8] "java/lang/Boolean"
// * [CONSTANT_Class_info] for above
// * [UTF-8] "(Z)V"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "booleanValue"
// * [UTF-8] "()Z"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "java/lang/Byte"
// * [CONSTANT_Class_info] for above
// * [UTF-8] "(B)V"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "byteValue"
// * [UTF-8] "()B"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "java/lang/Character"
// * [CONSTANT_Class_info] for above
// * [UTF-8] "(C)V"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "charValue"
// * [UTF-8] "()C"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "java/lang/Double"
// * [CONSTANT_Class_info] for above
// * [UTF-8] "(D)V"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "doubleValue"
// * [UTF-8] "()D"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "java/lang/Float"
// * [CONSTANT_Class_info] for above
// * [UTF-8] "(F)V"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "floatValue"
// * [UTF-8] "()F"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "java/lang/Integer"
// * [CONSTANT_Class_info] for above
// * [UTF-8] "(I)V"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "intValue"
// * [UTF-8] "()I"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "java/lang/Long"
// * [CONSTANT_Class_info] for above
// * [UTF-8] "(J)V"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "longValue"
// * [UTF-8] "()J"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "java/lang/Short"
// * [CONSTANT_Class_info] for above
// * [UTF-8] "(S)V"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
// * [UTF-8] "shortValue"
// * [UTF-8] "()S"
// * [CONSTANT_NameAndType_info] for above
// * [CONSTANT_Methodref_info] for above
short numCPEntries = NUM_BASE_CPOOL_ENTRIES + NUM_COMMON_CPOOL_ENTRIES;
boolean usesPrimitives = usesPrimitiveTypes();
if (usesPrimitives) {
numCPEntries += NUM_BOXING_CPOOL_ENTRIES;
}
if (forSerialization) {
numCPEntries += NUM_SERIALIZATION_CPOOL_ENTRIES;
}
// Add in variable-length number of entries to be able to describe
// non-primitive parameter types and checked exceptions.
numCPEntries += (short) (2 * numNonPrimitiveParameterTypes());
asm.emitShort(add(numCPEntries, S1));
final String generatedName = generateName(isConstructor, forSerialization);
asm.emitConstantPoolUTF8(generatedName);
asm.emitConstantPoolClass(asm.cpi());
thisClass = asm.cpi();
if (isConstructor) {
if (forSerialization) {
asm.emitConstantPoolUTF8
("jdk/internal/reflect/SerializationConstructorAccessorImpl");
} else {
asm.emitConstantPoolUTF8("jdk/internal/reflect/ConstructorAccessorImpl");
}
} else {
asm.emitConstantPoolUTF8("jdk/internal/reflect/MethodAccessorImpl");
}
asm.emitConstantPoolClass(asm.cpi());
superClass = asm.cpi();
asm.emitConstantPoolUTF8(getClassName(declaringClass, false));
asm.emitConstantPoolClass(asm.cpi());
targetClass = asm.cpi();
short serializationTargetClassIdx = (short) 0;
if (forSerialization) {
asm.emitConstantPoolUTF8(getClassName(serializationTargetClass, false));
asm.emitConstantPoolClass(asm.cpi());
serializationTargetClassIdx = asm.cpi();
}
asm.emitConstantPoolUTF8(name);
asm.emitConstantPoolUTF8(buildInternalSignature());
asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
if (isInterface()) {
asm.emitConstantPoolInterfaceMethodref(targetClass, asm.cpi());
} else {
if (forSerialization) {
asm.emitConstantPoolMethodref(serializationTargetClassIdx, asm.cpi());
} else {
asm.emitConstantPoolMethodref(targetClass, asm.cpi());
}
}
targetMethodRef = asm.cpi();
if (isConstructor) {
asm.emitConstantPoolUTF8("newInstance");
} else {
asm.emitConstantPoolUTF8("invoke");
}
invokeIdx = asm.cpi();
if (isConstructor) {
asm.emitConstantPoolUTF8("([Ljava/lang/Object;)Ljava/lang/Object;");
} else {
asm.emitConstantPoolUTF8
("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
}
invokeDescriptorIdx = asm.cpi();
// Output class information for non-primitive parameter types
nonPrimitiveParametersBaseIdx = add(asm.cpi(), S2);
for (int i = 0; i < parameterTypes.length; i++) {
Class<?> c = parameterTypes[i];
if (!isPrimitive(c)) {
asm.emitConstantPoolUTF8(getClassName(c, false));
asm.emitConstantPoolClass(asm.cpi());
}
}
// Entries common to FieldAccessor, MethodAccessor and ConstructorAccessor
emitCommonConstantPoolEntries();
// Boxing entries
if (usesPrimitives) {
emitBoxingContantPoolEntries();
}
if (asm.cpi() != numCPEntries) {
throw new InternalError("Adjust this code (cpi = " + asm.cpi() +
", numCPEntries = " + numCPEntries + ")");
}
// Access flags
asm.emitShort(ACC_PUBLIC);
// This class
asm.emitShort(thisClass);
// Superclass
asm.emitShort(superClass);
// Interfaces count and interfaces
asm.emitShort(S0);
// Fields count and fields
asm.emitShort(S0);
// Methods count and methods
asm.emitShort(NUM_METHODS);
emitConstructor();
emitInvoke();
// Additional attributes (none)
asm.emitShort(S0);
// Load class
vec.trim();
final byte[] bytes = vec.getData();
// Note: the class loader is the only thing that really matters
// here -- it's important to get the generated code into the
// same namespace as the target class. Since the generated code
// is privileged anyway, the protection domain probably doesn't
// matter.
return AccessController.doPrivileged(
new PrivilegedAction<MagicAccessorImpl>() {
@SuppressWarnings("deprecation") // Class.newInstance
public MagicAccessorImpl run() {
try {
return (MagicAccessorImpl)
ClassDefiner.defineClass
(generatedName,
bytes,
0,
bytes.length,
declaringClass.getClassLoader()).newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new InternalError(e);
}
}
});
}
/** This emits the code for either invoke() or newInstance() */
private void emitInvoke() {
// NOTE that this code will only handle 65535 parameters since we
// use the sipush instruction to get the array index on the
// operand stack.
if (parameterTypes.length > 65535) {
throw new InternalError("Can't handle more than 65535 parameters");
}
// Generate code into fresh code buffer
ClassFileAssembler cb = new ClassFileAssembler();
if (isConstructor) {
// 1 incoming argument
cb.setMaxLocals(2);
} else {
// 2 incoming arguments
cb.setMaxLocals(3);
}
short illegalArgStartPC = 0;
if (isConstructor) {
// Instantiate target class before continuing
// new <target class type>
// dup
cb.opc_new(targetClass);
cb.opc_dup();
} else {
// Get target object on operand stack if necessary.
// We need to do an explicit null check here; we won't see
// NullPointerExceptions from the invoke bytecode, since it's
// covered by an exception handler.
if (!isStatic()) {
// aload_1
// ifnonnull <checkcast label>
// new <NullPointerException>
// dup
// invokespecial <NullPointerException ctor>
// athrow
// <checkcast label:>
// aload_1
// checkcast <target class's type>
cb.opc_aload_1();
Label l = new Label();
cb.opc_ifnonnull(l);
cb.opc_new(nullPointerClass);
cb.opc_dup();
cb.opc_invokespecial(nullPointerCtorIdx, 0, 0);
cb.opc_athrow();
l.bind();
illegalArgStartPC = cb.getLength();
cb.opc_aload_1();
cb.opc_checkcast(targetClass);
}
}
// Have to check length of incoming array and throw
// IllegalArgumentException if not correct. A concession to the
// JCK (isn't clearly specified in the spec): we allow null in the
// case where the argument list is zero length.
// if no-arg:
// aload_2 | aload_1 (Method | Constructor)
// ifnull <success label>
// aload_2 | aload_1
// arraylength
// sipush <num parameter types>
// if_icmpeq <success label>
// new <IllegalArgumentException>
// dup
// invokespecial <IllegalArgumentException ctor>
// athrow
// <success label:>
Label successLabel = new Label();
if (parameterTypes.length == 0) {
if (isConstructor) {
cb.opc_aload_1();
} else {
cb.opc_aload_2();
}
cb.opc_ifnull(successLabel);
}
if (isConstructor) {
cb.opc_aload_1();
} else {
cb.opc_aload_2();
}
cb.opc_arraylength();
cb.opc_sipush((short) parameterTypes.length);
cb.opc_if_icmpeq(successLabel);
cb.opc_new(illegalArgumentClass);
cb.opc_dup();
cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0);
cb.opc_athrow();
successLabel.bind();
// Iterate through incoming actual parameters, ensuring that each
// is compatible with the formal parameter type, and pushing the
// actual on the operand stack (unboxing and widening if necessary).
short paramTypeCPIdx = nonPrimitiveParametersBaseIdx;
Label nextParamLabel = null;
byte count = 1; // both invokeinterface opcode's "count" as well as
// num args of other invoke bytecodes
for (int i = 0; i < parameterTypes.length; i++) {
Class<?> paramType = parameterTypes[i];
count += (byte) typeSizeInStackSlots(paramType);
if (nextParamLabel != null) {
nextParamLabel.bind();
nextParamLabel = null;
}
// aload_2 | aload_1
// sipush <index>
// aaload
if (isConstructor) {
cb.opc_aload_1();
} else {
cb.opc_aload_2();
}
cb.opc_sipush((short) i);
cb.opc_aaload();
if (isPrimitive(paramType)) {
// Unboxing code.
// Put parameter into temporary local variable
// astore_3 | astore_2
if (isConstructor) {
cb.opc_astore_2();
} else {
cb.opc_astore_3();
}
// repeat for all possible widening conversions:
// aload_3 | aload_2
// instanceof <primitive boxing type>
// ifeq <next unboxing label>
// aload_3 | aload_2
// checkcast <primitive boxing type> // Note: this is "redundant",
// // but necessary for the verifier
// invokevirtual <unboxing method>
// <widening conversion bytecode, if necessary>
// goto <next parameter label>
// <next unboxing label:> ...
// last unboxing label:
// new <IllegalArgumentException>
// dup
// invokespecial <IllegalArgumentException ctor>
// athrow
Label l = null; // unboxing label
nextParamLabel = new Label();
for (int j = 0; j < primitiveTypes.length; j++) {
Class<?> c = primitiveTypes[j];
if (canWidenTo(c, paramType)) {
if (l != null) {
l.bind();
}
// Emit checking and unboxing code for this type
if (isConstructor) {
cb.opc_aload_2();
} else {
cb.opc_aload_3();
}
cb.opc_instanceof(indexForPrimitiveType(c));
l = new Label();
cb.opc_ifeq(l);
if (isConstructor) {
cb.opc_aload_2();
} else {
cb.opc_aload_3();
}
cb.opc_checkcast(indexForPrimitiveType(c));
cb.opc_invokevirtual(unboxingMethodForPrimitiveType(c),
0,
typeSizeInStackSlots(c));
emitWideningBytecodeForPrimitiveConversion(cb,
c,
paramType);
cb.opc_goto(nextParamLabel);
}
}
if (l == null) {
throw new InternalError
("Must have found at least identity conversion");
}
// Fell through; given object is null or invalid. According to
// the spec, we can throw IllegalArgumentException for both of
// these cases.
l.bind();
cb.opc_new(illegalArgumentClass);
cb.opc_dup();
cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0);
cb.opc_athrow();
} else {
// Emit appropriate checkcast
cb.opc_checkcast(paramTypeCPIdx);
paramTypeCPIdx = add(paramTypeCPIdx, S2);
// Fall through to next argument
}
}
// Bind last goto if present
if (nextParamLabel != null) {
nextParamLabel.bind();
}
short invokeStartPC = cb.getLength();
// OK, ready to perform the invocation.
if (isConstructor) {
cb.opc_invokespecial(targetMethodRef, count, 0);
} else {
if (isStatic()) {
cb.opc_invokestatic(targetMethodRef,
count,
typeSizeInStackSlots(returnType));
} else {
if (isInterface()) {
cb.opc_invokeinterface(targetMethodRef,
count,
count,
typeSizeInStackSlots(returnType));
} else {
cb.opc_invokevirtual(targetMethodRef,
count,
typeSizeInStackSlots(returnType));
}
}
}
short invokeEndPC = cb.getLength();
if (!isConstructor) {
// Box return value if necessary
if (isPrimitive(returnType)) {
cb.opc_invokestatic(boxingMethodForPrimitiveType(returnType),
typeSizeInStackSlots(returnType),
0);
} else if (returnType == Void.TYPE) {
cb.opc_aconst_null();
}
}
cb.opc_areturn();
// We generate two exception handlers; one which is responsible
// for catching ClassCastException and NullPointerException and
// throwing IllegalArgumentException, and the other which catches
// all java/lang/Throwable objects thrown from the target method
// and wraps them in InvocationTargetExceptions.
short classCastHandler = cb.getLength();
// ClassCast, etc. exception handler
cb.setStack(1);
cb.opc_invokespecial(toStringIdx, 0, 1);
cb.opc_new(illegalArgumentClass);
cb.opc_dup_x1();
cb.opc_swap();
cb.opc_invokespecial(illegalArgumentStringCtorIdx, 1, 0);
cb.opc_athrow();
short invocationTargetHandler = cb.getLength();
// InvocationTargetException exception handler
cb.setStack(1);
cb.opc_new(invocationTargetClass);
cb.opc_dup_x1();
cb.opc_swap();
cb.opc_invokespecial(invocationTargetCtorIdx, 1, 0);
cb.opc_athrow();
// Generate exception table. We cover the entire code sequence
// with an exception handler which catches ClassCastException and
// converts it into an IllegalArgumentException.
ClassFileAssembler exc = new ClassFileAssembler();
exc.emitShort(illegalArgStartPC); // start PC
exc.emitShort(invokeStartPC); // end PC
exc.emitShort(classCastHandler); // handler PC
exc.emitShort(classCastClass); // catch type
exc.emitShort(illegalArgStartPC); // start PC
exc.emitShort(invokeStartPC); // end PC
exc.emitShort(classCastHandler); // handler PC
exc.emitShort(nullPointerClass); // catch type
exc.emitShort(invokeStartPC); // start PC
exc.emitShort(invokeEndPC); // end PC
exc.emitShort(invocationTargetHandler); // handler PC
exc.emitShort(throwableClass); // catch type
emitMethod(invokeIdx, cb.getMaxLocals(), cb, exc,
new short[] { invocationTargetClass });
}
private boolean usesPrimitiveTypes() {
// We need to emit boxing/unboxing constant pool information if
// the method takes a primitive type for any of its parameters or
// returns a primitive value (except void)
if (returnType.isPrimitive()) {
return true;
}
for (int i = 0; i < parameterTypes.length; i++) {
if (parameterTypes[i].isPrimitive()) {
return true;
}
}
return false;
}
private int numNonPrimitiveParameterTypes() {
int num = 0;
for (int i = 0; i < parameterTypes.length; i++) {
if (!parameterTypes[i].isPrimitive()) {
++num;
}
}
return num;
}
private boolean isInterface() {
return declaringClass.isInterface();
}
private String buildInternalSignature() {
StringBuilder sb = new StringBuilder();
sb.append("(");
for (int i = 0; i < parameterTypes.length; i++) {
sb.append(getClassName(parameterTypes[i], true));
}
sb.append(")");
sb.append(getClassName(returnType, true));
return sb.toString();
}
private static synchronized String generateName(boolean isConstructor,
boolean forSerialization)
{
if (isConstructor) {
if (forSerialization) {
int num = ++serializationConstructorSymnum;
return "jdk/internal/reflect/GeneratedSerializationConstructorAccessor" + num;
} else {
int num = ++constructorSymnum;
return "jdk/internal/reflect/GeneratedConstructorAccessor" + num;
}
} else {
int num = ++methodSymnum;
return "jdk/internal/reflect/GeneratedMethodAccessor" + num;
}
}
}

@ -1,45 +0,0 @@
/*
* Copyright (c) 2001, 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 jdk.internal.reflect;
/** <P> Java serialization (in java.io) expects to be able to
instantiate a class and invoke a no-arg constructor of that
class's first non-Serializable superclass. This is not a valid
operation according to the VM specification; one can not (for
classes A and B, where B is a subclass of A) write "new B;
invokespecial A()" without getting a verification error. </P>
<P> In all other respects, the bytecode-based reflection framework
can be reused for this purpose. This marker class was originally
known to the VM and verification disabled for it and all
subclasses, but the bug fix for 4486457 necessitated disabling
verification for all of the dynamically-generated bytecodes
associated with reflection. This class has been left in place to
make future debugging easier. </P> */
abstract class SerializationConstructorAccessorImpl
extends ConstructorAccessorImpl {
}