Accessing private variable inside a library class

edited May 2016 in Library Questions

I am trying to get an array from inside a library class, but the field is set as private :((

I used a java decompiler website to see this source of code:

public class MultiMarker
 extends NyARPsgBaseClass {
 protected PImageSensor _ss;
 protected NyARMarkerSystem _ms;
 public static final double DEFAULT_CF_THRESHOLD = 0.51;
 public static final int DEFAULT_LOST_DELAY = 10;
 public static final int THLESHOLD_AUTO = -1;
 private ArrayList<Integer> _id_map = new ArrayList();  //<<------- I WANT TO ACCESS THIS
 private final PMatrix3D _ps_projection = new PMatrix3D();
 private boolean _is_in_begin_end_session = false;

So this is what I had tried following some examples using Java as reference but still variable is NOT VISIBLE. maybe some casting problem...

import java.lang.reflect.*;
import jp.nyatla.nyar4psg.*;

MultiMarker nya;
void setup() {
  size(640,360);
  nya=new MultiMarker(this, 640, 360, "camera_para.dat", NyAR4PsgConfig.CONFIG_PSG);
  nya.addARMarker("patt.hiro", 80);//id=0
  nya.addARMarker("patt.kanji", 80);//id=1

  try {
      MultiMarker.class.getDeclaredField("_id_map").setAccessible(true);
      //or
      //Field idmap = MultiMarker.class.getDeclaredField("_id_map");
      //idmap.setAccessible(true);
      // ArrayList<Integer> castTest = idmap.get( ArrayList<Integer>() ); //--error
      // ArrayList<Integer> castTest = (ArrayList<Integer>)idmap.get(idmap); //--error

  }    
    catch (ReflectiveOperationException e) {
    throw new RuntimeException(e);
  }

  println(nya._id_map.size()); //field is not visible
}

Answers

  • edited May 2016

    Yes, so I have read these examples and tried to implement in the code above. I have read the reflect.class documentation and I believe maybe the problem is how I am trying to retrieve the ArrayList object using the Field.get( obj ).

    But no. I have tried to access a private boolean variable using Field.getBoolean(obj) but I got "Can not set boolean field jp.nyatla......MultiMarker._is_in_begin_end_session to java.lang.reflect.Field" error

    So it wasn't a casting problem as I expected...

  • edited May 2016

    Gonna try to implement a more general approach and post it here when ready. :-h

  • edited May 2016

    Thank you GoToLoop!! Got it working finally. Problem was using wrong object inside the Field.get method. #-o

    import jp.nyatla.nyar4psg.*;
    import java.lang.reflect.*;
    
    MultiMarker nya;
    ArrayList<Integer> idmapArray;
    
    void setup() {
      size(640, 360);
      nya=new MultiMarker(this, 640, 360, "camera_para.dat", NyAR4PsgConfig.CONFIG_PSG);
      nya.addARMarker("patt.hiro", 80);//id=0
      nya.addARMarker("patt.kanji", 80);//id=1
    
      try {
        Field idmap = MultiMarker.class.getDeclaredField("_id_map");
        idmap.setAccessible(true);
        idmapArray = (ArrayList<Integer>)idmap.get(nya); //i was using generic obj here
      }    
      catch (ReflectiveOperationException e) {
        throw new RuntimeException(e);
      }
      println(idmapArray.size()); //print 2 OK!!
    }
    
    /*
    public class MultiMarker
     extends NyARPsgBaseClass {
     protected PImageSensor _ss;
     protected NyARMarkerSystem _ms;
     public static final double DEFAULT_CF_THRESHOLD = 0.51;
     public static final int DEFAULT_LOST_DELAY = 10;
     public static final int THLESHOLD_AUTO = -1;
     private ArrayList<Integer> _id_map = new ArrayList();  //<<------- I WANT TO ACCESS THIS
     private final PMatrix3D _ps_projection = new PMatrix3D();
     private boolean _is_in_begin_end_session = false;
     */
    
  • edited May 2016 Answer ✓

    @bontempos, congratz for solving it alone. <:-P
    Nonetheless, gonna leave the general solution here as reference for others: O:-)

    /**
     * Get Private Field Example (v1.0.1)
     * GoToLoop (2016-May-23)
     *
     * forum.Processing.org/two/discussion/16771/
     * accessing-private-variable-inside-a-library-class
     */
    
    import java.lang.reflect.Field;
    
    void setup() {
      Table t = new Table();
      t.addRow();
      t.addRow();
      t.addRow();
    
      TableRow tr = t.getRow(1);
      Field f = getField(tr, "row");
    
      int r = (int) readField(f, tr);
      println(r); // 1
    
      writeField(f, tr, -2500);
      r = (int) readField(f, tr);
      println(r); // -2500
    
      exit();
    }
    
    static final Field getField(Object obj, String s) {
      return getField(obj.getClass(), s);
    }
    
    static final Field getField(Class<?> c, String s) {
      try {
        return c.getDeclaredField(s);
      }
    
      catch (NoSuchFieldException e) {
        System.err.println(e);
        return null;
      }
    }
    
    static final Object readField(Field f, Object obj) {
      f.setAccessible(true);
    
      try {
        return f.get(obj);
      }
    
      catch (IllegalAccessException e) {
        System.err.println(e);
        return null;
      }
    }
    
    static final void writeField(Field f, Object obj, Object val) {
      f.setAccessible(true);
    
      try {
        f.set(obj, val);
      }
    
      catch (IllegalAccessException e) {
        System.err.println(e);
      }
    }
    
Sign In or Register to comment.