এমনকি সত্ত্বেও final
ক্ষেত্র স্ট্যাটিক ইনিশিয়ালাইজারের বাইরেও সংশোধন করা যেতে পারে এবং (কমপক্ষে জেভিএম হটস্পট) বাইটকোডকে পুরোপুরি সূক্ষ্মভাবে কার্যকর করবে।
সমস্যাটি হচ্ছে জাভা সংকলক এটির অনুমতি দেয় না তবে এটি ব্যবহার করে সহজেই বাইপাস করা যায় objectweb.asm
। এখানে পুরোপুরি বৈধ ক্লাসফাইল যা বাইকোড যাচাইকরণটি পাস করে এবং জেভিএম হটস্পট ওপেনজেডি কে 12 এর অধীনে সাফল্যের সাথে লোড এবং আর্কিটাইজড:
ClassWriter cw = new ClassWriter(0);
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, "Cl", null, "java/lang/Object", null);
{
FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, "fld", "I", null, null);
fv.visitEnd();
}
{
// public void setFinalField1() { //... }
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "setFinalField1", "()V", null, null);
mv.visitMaxs(2, 1);
mv.visitInsn(Opcodes.ICONST_5);
mv.visitFieldInsn(Opcodes.PUTSTATIC, "Cl", "fld", "I");
mv.visitInsn(Opcodes.RETURN);
mv.visitEnd();
}
{
// public void setFinalField2() { //... }
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "setFinalField2", "()V", null, null);
mv.visitMaxs(2, 1);
mv.visitInsn(Opcodes.ICONST_2);
mv.visitFieldInsn(Opcodes.PUTSTATIC, "Cl", "fld", "I");
mv.visitInsn(Opcodes.RETURN);
mv.visitEnd();
}
cw.visitEnd();
জাভাতে, ক্লাসটি মোটামুটিভাবে নীচের দিকে কথা বলেছে:
public class Cl{
private static final int fld;
public static void setFinalField1(){
fld = 5;
}
public static void setFinalField2(){
fld = 2;
}
}
যা সংকলন করা যায় না javac
, তবে জেভিএম দ্বারা লোড এবং সম্পাদন করা যায়।
জেভিএম হটস্পটের এই ধরণের ক্লাসগুলির জন্য বিশেষভাবে চিকিত্সা রয়েছে যে এটি এই ধরণের "ধ্রুবকদের "কে ধ্রুবক ভাঁজিতে অংশ নিতে বাধা দেয়। এই চেকটি ক্লাস আরম্ভের বাইটকোড পুনর্লিখনের পর্যায়ে করা হয় :
// Check if any final field of the class given as parameter is modified
// outside of initializer methods of the class. Fields that are modified
// are marked with a flag. For marked fields, the compilers do not perform
// constant folding (as the field can be changed after initialization).
//
// The check is performed after verification and only if verification has
// succeeded. Therefore, the class is guaranteed to be well-formed.
InstanceKlass* klass = method->method_holder();
u2 bc_index = Bytes::get_Java_u2(bcp + prefix_length + 1);
constantPoolHandle cp(method->constants());
Symbol* ref_class_name = cp->klass_name_at(cp->klass_ref_index_at(bc_index));
if (klass->name() == ref_class_name) {
Symbol* field_name = cp->name_ref_at(bc_index);
Symbol* field_sig = cp->signature_ref_at(bc_index);
fieldDescriptor fd;
if (klass->find_field(field_name, field_sig, &fd) != NULL) {
if (fd.access_flags().is_final()) {
if (fd.access_flags().is_static()) {
if (!method->is_static_initializer()) {
fd.set_has_initialized_final_update(true);
}
} else {
if (!method->is_object_initializer()) {
fd.set_has_initialized_final_update(true);
}
}
}
}
}
}
জেভিএম হটস্পট যাচাই করে এমন একমাত্র বিধিনিষেধটি হ'ল final
ক্ষেত্রটি ক্লাসের বাইরে যে final
ক্ষেত্রটি ঘোষিত হয়েছে তার বাইরে পরিবর্তন করা উচিত নয় ।