CORRECTIF : Classe doit être manipulé pour l’initialisation statique se produit lors du chargement par SecurityClassLoader

SYMPTÔMES

Lorsque vous dérivez de la classe SecurityClassLoader , comme décrit dans le Kit de développement de la documentation de Java, à associer des autorisations à des classes chargées, les variables statiques de classes chargées ne sont pas initialisées tant que la classe est touchée par l’instanciation d’une nouvelle instance ou appeler une méthode sur la classe. Ce comportement est par défaut.

CAUSE

Un indicateur d’optimisation est activé par défaut.

Résolution

Ce problème a été résolu dans la build 3155 de la machine virtuelle Microsoft. Si vous utilisez le Microsoft Raw Native Interface RNI (), vous pouvez contourner ce problème en définissant une variable de membre privé de la classe SecurityClassLoader . Consultez l’exemple RNI ci-dessous.

ÉTAT

Microsoft a confirmé l'existence de ce problème dans les produits Microsoft répertoriés au début de cet article.

Plus d'informations

Procédure pour reproduire le comportement

  • Compilez et exécutez le code suivant.
  • Suivez les instructions dans les commentaires de code.
  • Si vous utilisez une version de la machine virtuelle Microsoft antérieure à 3155, les valeurs des variables statiques n’ont pas été définies.
  • Dans le cas contraire, les valeurs s’affichent dans la MessageBox comme prévu.

Code de Java

import java.io.*;import com.ms.security.*;import com.ms.win32.*;public class SecureLoader extends SecurityClassLoader{  private static File f;  private FileInputStream fis;  private byte[] loadClassData(String class_name) throws Exception  {    // Change this as needed to reflect the path     // to the appropriate .class file TestClass.class.    // Note that you will also want to make sure that    // the class file does not exist on the system    // CLASSPATH, or it will be loaded by the System     // ClassLoader and not your custom SecurityClassLoader.    f = new File("D:/VJProj/RNIBug/" + class_name + ".class");    synchronized (f)    {      try       {        byte[] data = new byte[(int)f.length()];        fis = new FileInputStream(f);        fis.read(data);        return data;              }      finally       {        fis.close();      }    }  }  protected Class loadClass(String class_name, boolean resolve_class)    throws ClassNotFoundException  {    Class cl = null;    try     {      cl = findSystemClass(class_name);    }    catch (Exception e)    {      try       {        byte[] class_data = loadClassData(class_name);        PermissionDataSet pds = new PermissionDataSet();        pds.setFullyTrusted(true);        PermissionSet perms = new PermissionSet(pds);        cl = defineClass(class_name,                          class_data,                          0,                          class_data.length,                          perms,                          (java.security.Principal)null);              }      catch (Exception e2)      {        WinUtil.alert(e2);      }    }        if (resolve_class)      resolveClass(cl);    return cl;  }}class WinUtil{  public static void alert(Object o)  {    User32.MessageBox(0,                      o.toString(),                      "Alert",                      0);  }}/***************************************************/ import java.lang.reflect.*;public class TestRun{  public static void main(String[] args)  {    try     {      SecureLoader sl = new SecureLoader();      Class cl = sl.loadClass("TestClass", true);            // Comment the following two lines to reproduce the problem.            Object o = cl.newInstance();      WinUtil.alert(o);             // Indicates that we have an instance of TestClass.      // We are unable to typecast this Object to TestClass, as      // TestClass was loaded by the custom ClassLoader SecureLoader.            Field f = cl.getField("staticBlockInt");      int staticBlockInt = f.getInt(cl);            f = cl.getField("staticInt");      int staticInt = f.getInt(cl);      String message = "This string is a result ";      message += "of the TestClass.testMethod() call.\n";      message += "The value of staticInt is "+staticInt+"\n";      message += "The value of staticBlockInt is "+staticBlockInt+"\n";            WinUtil.alert(message);    }    catch (Exception e)    {      WinUtil.alert(e);    }  }}/***********************************************************/ public class TestClass{   public static int staticInt = 10;   public static int staticBlockInt;         static   {      staticBlockInt = 20;   }      // We are over-riding toString to indicate   // that we do indeed have an instance of the   // class that we want.   public String toString()   {     return "TestClass";   }}

CODE DE RNI

Remarque: Assurez-vous que les classes Java utilisées dans le code suivant se trouvent sur le chemin de classe.
#include <windows.h>#include <stdio.h>#include <native.h>void checkForError();void main(int argc, char *argv[]){  static const int LATE_CLINIT = -1;  static const int EARLY_CLINIT = 1;  static const int NOT_INITIALIZED = 0;    static int staticInt = 0;  static int staticBlockInt = 0;  int initval = 0;    ThreadEntryFrame threadEntryFrame;    ClassClass* pcMyLoader = NULL;  ClassClass* pcLoadedClass = NULL;    HObject* phMyLoaderInst = NULL;    fieldblock* pFieldBlock = NULL;    if (PrepareThreadForJava(&threadEntryFrame))   {    pcMyLoader = FindClass(NULL, "SecureLoader", TRUE);        checkForError();        if (pcMyLoader)     {      phMyLoaderInst = execute_java_constructor(        NULL,        "SecureLoader",        pcMyLoader,        "()");          } else {      printf("SecureLoader not found.");      Sleep(3000);    }        if (phMyLoaderInst)    {      pFieldBlock = Class_GetField(pcMyLoader,         "initialized");            initval = Field_GetValue(phMyLoaderInst,         pFieldBlock);            printf("The value of initialized is %d.\n",         initval);            // This switch block is the work-around.      // Comment this out to reproduce the problem.      switch (initval)      {      case LATE_CLINIT:        Field_SetValue(phMyLoaderInst,           pFieldBlock,           EARLY_CLINIT);                pFieldBlock = Class_GetField(pcMyLoader,           "initialized");                initval = Field_GetValue(phMyLoaderInst,           pFieldBlock);        break;              case NOT_INITIALIZED:        checkForError();        break;              case EARLY_CLINIT:        break;      }            printf("The value of initialized is now:  %d\n",         initval);            pcLoadedClass = (ClassClass*)execute_java_dynamic_method(        NULL,        phMyLoaderInst,        "loadClass",        "(Ljava/lang/String;Z)Ljava/lang/Class;",        makeJavaString("TestClass", strlen("TestClass")),        TRUE);    } else      checkForError();        if (pcLoadedClass)    {      pFieldBlock = Class_GetField(pcLoadedClass,         "staticInt");            staticInt = Field_GetValue(NULL,         pFieldBlock);            printf("The value of staticInt is %d.\n",         staticInt);            pFieldBlock = Class_GetField(pcLoadedClass,         "staticBlockInt");            staticBlockInt = Field_GetValue(NULL,         pFieldBlock);            printf("The value of staticBlockInt is %d.\n",         staticBlockInt);            Sleep(3000);          } else      checkForError();        UnprepareThreadForJava(&threadEntryFrame);      }}void checkForError(){  if (getPendingException(NULL))  {    exceptionDescribe(NULL);    Sleep(3000);    exceptionClear(NULL);  }}

RÉFÉRENCES

Pour des informations sur Visual J ++ et SDK pour Java, visitez le site Web de Microsoft à l’adresse suivante :
Propriétés

ID d'article : 219280 - Dernière mise à jour : 15 févr. 2017 - Révision : 1

Microsoft Virtual Machine for Java, Microsoft Visual J++ 1.0 Édition standard, Microsoft Visual J++ 1.1 Édition standard, Microsoft Visual J++ 6.0 Édition standard, Microsoft Software Development Kit for Java 1.0, Microsoft Software Development Kit for Java 1.5, Microsoft Software Development Kit for Java 1.51, Microsoft Software Development Kit for Java 2.02, Microsoft Software Development Kit for Java 2.02, Microsoft Software Development Kit for Java 2.01, Microsoft Software Development Kit for Java 2.02, Microsoft Software Development Kit for Java 2.02, Microsoft Software Development Kit for Java 3.0, Microsoft Software Development Kit for Java 3.0, Microsoft Software Development Kit for Java 3.0, Microsoft Software Development Kit for Java 3.0, Microsoft Software Development Kit for Java 3.1

Commentaires