# Tester for the PAppletFinder in Processing 4 required

**URL:** https://discourse.processing.org/t/tester-for-the-pappletfinder-in-processing-4-required/38914
**Category:** Gallery
**Created:** [September 21, 2022, 2:08pm UTC](https://discourse.processing.org/t/tester-for-the-pappletfinder-in-processing-4-required/38914 "2022-09-21T14:08:37Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![NumericPrime](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/numericprime/32/16318_2.png) [@NumericPrime](https://discourse.processing.org/u/NumericPrime)
#### Post date: [September 21, 2022, 2:08pm UTC](https://discourse.processing.org/t/tester-for-the-pappletfinder-in-processing-4-required/38914/1 "2022-09-21T14:08:37Z")

</div>

I am currently writing a library to provide Utility to others writing processing libraries. A core feature is the detection of all PApplet instances.  
After 4 months of development I finally found a possibility that should work for both Processing 3 and 4 I would like however assert that it really works with Processing 4.

(This is the according thread in the forum: [Get the current instance of PApplet from a library - Processing / Coding Questions - Processing Foundation](https://discourse.processing.org/t/get-the-current-instance-of-papplet-from-a-library/36925/23))

This sketch utilizes a .java tab:

**PAppletFinder.java**

```auto

import processing.awt.*;
import processing.opengl.*;
import processing.core.*;

import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.lang.reflect.*;

import sun.misc.*;
/**This class finds the active PApplet (Processing program)
 @author NumericPrime*/
public class PAppletFinder {
  /**Unsafe instance used*/
  public static Unsafe unsafe=null;
  /**Unsafe Field offset*/
  public static long fieldIndex=0;
  /**Target field of the thread*/
  public static Field threadTargField=null;
  /**Here the three Fields unsafe,fieldIndex, threadTargField are initalized*/
  static {
    try {
      Field f2=Unsafe.class.getDeclaredField("theUnsafe");
      f2.setAccessible(true);
      unsafe=(Unsafe) f2.get(null);
      //System.out.println("Unsafe instance: "+unsafe.toString());
      threadTargField=Thread.class.getDeclaredField("target");
      fieldIndex=unsafe.objectFieldOffset(threadTargField);
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }
  /**Getter-Method used to detect all PApplets. If the detection hasn't run yet this method will run it.
   @param refresh if true: redetects all PApplets
   @return all detected PApplets*/
  public static PApplet[] getPApplets(boolean refresh) {
    int allfpSize=0;
    if (refresh) allFoundPapplets.clear();
    if ((allfpSize=allFoundPapplets.size())==0) findAll();
    return allFoundPapplets.toArray(new PApplet[allfpSize]);
  }
  /**All results will be saved here*/
  public static java.util.List<PApplet> allFoundPapplets=new LinkedList<PApplet>();
  /**This class takes the contents of the window and pieces together the PApplet
   * @return PApplet of the current sketch.
   * @param c contents of the Processing window (must be a SmoothCanvas)*/
  public static void get(Component c) {
    //System.out.println("Processing Window content");
    PSurfaceAWT.SmoothCanvas sc=(PSurfaceAWT.SmoothCanvas) c;
    try {
      //gets the PSurface for the PApplet
      PSurfaceAWT psa=(PSurfaceAWT) get(sc, "this$0", sc.getClass());
      //gets the PApplet
      PApplet prg=(PApplet) get((PSurfaceNone)psa, "sketch", PSurfaceNone.class);
      allFoundPapplets.add(prg);
    }
    catch(Exception e) {
      //System.err.println("Something went wrong");
      e.printStackTrace();
    }
  }
  /**This method tries to detect all PApplet used*/
  public static void findAll() {
    findFromWindow();
    fromThreads();
    //System.out.println("Detection done");
  }

  /**This looks out for processing-windows and gives the contents of the right one to the get method*/
  public static void findFromWindow() {
    //System.out.println("Searching Windows for instances");
    JFrame mainWindow=null;
    java.awt.Window win[]=java.awt.Window.getWindows();
    for (int i=0; i<win.length; i++) if (win[i] instanceof JFrame) {
      mainWindow=(JFrame) win[i];
      Component c=mainWindow.getContentPane().getComponents()[0];
      if (c instanceof PSurfaceAWT.SmoothCanvas) get(c);
    }
  }
  /**This is used to get the value of fields
   * @return Object value of a field
   * @param j the Object from which the value is taken
   * @param target name of the field
   * @param ref class the field is taken from*/
  public static Object get(Object j, String target, Class<?> ref) {
    try {
      Field f=ref.getDeclaredField(target);
      f.setAccessible(true);
      return f.get(j);
    } 
    catch (Exception e) {
      e.printStackTrace();
    } 
    return null;
  }
  /** When using P2D or P3D everything is built differently however there is a weakness to be found in 
    * PSurfaceJOGL as it dispatches a Thread using an annonymous inner class as Runnable*/
  public static void fromThreads() {
    //System.out.println("Searching Threads for instances");
    //This fetches all threads
    Set<Thread> threadSet=Thread.getAllStackTraces().keySet();
    //It iterates upon the threads to find ones dispatched by PSurfaceJOGL
    for (Thread th : threadSet) {
    iteration:
      {
        try {
          //Field f=th.getClass().getDeclaredField("target");
          //f.setAccessible(true);
          Object currinstance=null;
          
          //Here Unsafe is used to breach encapsulation of java.lang
          currinstance=unsafe.getObject(th, fieldIndex);
          if (!currinstance.getClass().toString().contains("PSurfaceJOGL$")) break iteration;
          //System.out.println("Weak spot found! "+th.getName());
          //gets the PSurfaceJOGL
          currinstance=getEnclosingInstance(currinstance);
          //gets the PApplet
          Field f=PSurfaceJOGL.class.getDeclaredField("sketch");
          f.setAccessible(true);
          allFoundPapplets.add((PApplet) (currinstance=f.get(currinstance)));
          //System.out.println("Detection successful");
        }
        catch(Exception e) 
        {
        catchBlock:
          {
            if (e instanceof NoSuchFieldException||e instanceof NullPointerException) {
              //System.err.println("target not found "+th.getName());
              //A NullPointerException may occur
              break catchBlock;
            }
            //System.err.println("Something went wrong!");
            e.printStackTrace();
          }
        }
      }
    }
  }
  //This will try to get the enclosing instance of an object (this can also be a lambda)
  public static Object getEnclosingInstance(Object o) {
    //This code will work for Processing 3 (uses annonymous inner classes)
    try {
      Class<?> classused=o.getClass();
      Field this0=classused.getDeclaredField("this$0");
      this0.setAccessible(true);
      return this0.get(o);
    }
    catch(Exception e) {
      //System.err.println("Can't find enclosing instance of Object, trying to use Lambdas... (To be expected with Processing 4)");
    }
    //This code should work for Processing 4 (lambdas are used instead of inner classes, Lambdas use arg$1 instead this$0) 
    try {
      Class<?> classused=o.getClass();
      Field this0=classused.getDeclaredField("arg$1");
      this0.setAccessible(true);
      return this0.get(o);
    }
    catch(Exception e) {
      //System.err.println("Detection Failed!");
    }
    return null;
  }
}

```

This is the code of the main sketch:

**MainSketch.pde**

```auto
void setup() {
  size(300,300,JAVA2D);
  println(this,PAppletFinder.getPApplets(false)[0]);
}
void draw() {
}

```

This should print something like:  
MainSketch@64638317 [MainSketch@64638317]

If it doesn’t please wirte the contents of the console, so I can try to debug it.  
Please also test this code with P3D and P2D.

---

<div class="post-metadata">

### Author: ![NumericPrime](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/numericprime/32/16318_2.png) [@NumericPrime](https://discourse.processing.org/u/NumericPrime)
#### Post date: [September 24, 2022, 4:27pm UTC](https://discourse.processing.org/t/tester-for-the-pappletfinder-in-processing-4-required/38914/2 "2022-09-24T16:27:55Z")

</div>

I had a friend run the code and it seems it doesn’t work for P2D and P3D in Processing 4.

The Problem is the following:  
Java 17 made the .setAccessible methods for the java.lang.\* classes not work anymore.  
When I try to access a field of **java.lang.** Thread it won’t work anymore. So back to the drawing board.

---

<div class="post-metadata">

### Author: ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)
#### Post date: [September 24, 2022, 5:35pm UTC](https://discourse.processing.org/t/tester-for-the-pappletfinder-in-processing-4-required/38914/3 "2022-09-24T17:35:09Z")

</div>

> [@Get the current instance of PApplet from a library](https://discourse.processing.org/t/get-the-current-instance-of-papplet-from-a-library/36925/25):
>
> Since Java 9 method [setAccessible()](https://docs.oracle.com/javase/9/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible-boolean-) also takes into consideration the module a reflected member belongs to: [https://en.Wikipedia.org/wiki/Java\_Platform\_Module\_System#Properties\_of\_modules](https://en.Wikipedia.org/wiki/Java_Platform_Module_System#Properties_of_modules) There’s an --add-opens option for the Java’s command-line, but dunno how to add that to Processing: [OpenJDK.org/jeps/261#Breaking-encapsulation](http://OpenJDK.org/jeps/261#Breaking-encapsulation)

---

<div class="post-metadata">

### Author: ![NumericPrime](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/numericprime/32/16318_2.png) [@NumericPrime](https://discourse.processing.org/u/NumericPrime)
#### Post date: [September 24, 2022, 6:31pm UTC](https://discourse.processing.org/t/tester-for-the-pappletfinder-in-processing-4-required/38914/4 "2022-09-24T18:31:40Z")

</div>

I might be able to do something with Unsafe:

```auto
import sun.misc.*;
import java.lang.reflect.*;
try{
Field f2=Unsafe.class.getDeclaredField("theUnsafe");
f2.setAccessible(true);
Unsafe o=(Unsafe) f2.get(null);
System.out.println("Unsafe instance: "+o.toString());
}catch(Exception e){e.printStackTrace();}

```

If this works with processing 4 I can try to use Unsafe to basicly do the same reflection does.

---

<div class="post-metadata">

### Author: ![NumericPrime](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/numericprime/32/16318_2.png) [@NumericPrime](https://discourse.processing.org/u/NumericPrime)
#### Post date: [September 25, 2022, 3:35pm UTC](https://discourse.processing.org/t/tester-for-the-pappletfinder-in-processing-4-required/38914/5 "2022-09-25T15:35:41Z")

</div>

> [@Get the current instance of PApplet from a library](https://discourse.processing.org/t/get-the-current-instance-of-papplet-from-a-library/36925/27):
>
> This code might do the trick. It also works with processing 3 and this code is able to breach encapsulation. (As long as there is no SecurityManager in place) PAppletFinder.java import processing.awt.\*; import processing.opengl.\*; import processing.core.\*; import javax.swing.\*; import java.awt.\*; import java.util.\*; import java.lang.reflect.\*; import sun.misc.\*; /\*\*This class finds the active PApplet (Processing program)\*/ public class PAppletFinder { /\*\*Unsafe instance used\*/ public sta…

---

<div class="post-metadata">

### Author: ![NumericPrime](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/numericprime/32/16318_2.png) [@NumericPrime](https://discourse.processing.org/u/NumericPrime)
#### Post date: [September 25, 2022, 7:15pm UTC](https://discourse.processing.org/t/tester-for-the-pappletfinder-in-processing-4-required/38914/6 "2022-09-25T19:15:18Z")

</div>

Good news everyone!

I managed to fix the issues arising from Processings change to Java 17. A friend of mine ran the code with Processing 4 and it works with the JAVA2D, P2D and P3D renderers.

I already fixed the code in the original post. Soon I will update the commentary and comment out the print commands.

If anyone got questions about how the code works feel free to ask!
