G4P crashing on launch

edited July 2015 in Library Questions

I've written a program that uses a bunch of sliders (and one checkbox) from G4P inside a window. I built the UI using the GUI builder tool, and modified the callbacks in the gui.pde file to set global variables. When I run this program, about 3/4 of the time it crashes on launch, either with a NullPointerException or ConcurrentModificationException. Below is a typical Java trace, as printed by Processing.

I find that if I hit Stop and then Run again, it sometimes works. If it fails, the trace that's printed is not always identical to the one below. Besides unpredictably being one kind of error or the other, they vary a little from one run to the next. It's like a roulette wheel where I fail about 75% of the time. Once the program launches, I don't have further problems.

I'm using Processing 2.2.1 on a Mac running OSX 10.10.3 and G4P re-installed from the Library Manager yesterday. I'd appreciate any help in correcting whatever is causing these launch problems. Thanks!

java.lang.NullPointerException
    at java.util.LinkedList$ListItr.next(LinkedList.java:891)
    at g4p_controls.GLabel.updateBuffer(Unknown Source)
    at g4p_controls.GLabel.draw(Unknown Source)
    at g4p_controls.GWindowInfo.draw(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1236)
    at processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1229)
    at processing.core.PApplet.handleMethods(PApplet.java:1423)
    at processing.core.PApplet.handleDraw(PApplet.java:2401)
    at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:240)
    at processing.core.PApplet.run(PApplet.java:2256)
    at java.lang.Thread.run(Thread.java:745)

Here is my main file. I stripped out everything but the bare bones, but I still get the errors above. I've tried specifying the JAVA2D renderer in the call to size() but that didn't prevent the crashes.

import g4p_controls.*;

// control parameters
int NumImages = 200;  // number of source images
float Offset = 0;       // [0-1], offset into image stack
float NumCycles = 1;    // >0, number of times to repeat
float Thickness = 1;    // >0, overall scaling factor on slices
boolean IncludeBlock = false;  // don't include the block by default
float BlockStart = .5;   // starting point of block
float BlockThickness = .1;  // thickness of block
int MergeCount = 1;     // number of slicers per call to marcher
boolean ReDraw = true;

void setup() {
  size(700, 700);
  createGUI();
} 

void draw() {
  if (!ReDraw) return;
  // stuff could go here, but we still reliably crash without it
  background(255);
  ReDraw = false;
}

Here is gui.pde. My only changes were to comment out the println() statements in the callbacks and insert changes to my globals.

/* =========================================================
 * ====                   WARNING                        ===
 * =========================================================
 * The code in this tab has been generated from the GUI form
 * designer and care should be taken when editing this file.
 * Only add/edit code inside the event handlers i.e. only
 * use lines between the matching comment tags. e.g.

 void myBtnEvents(GButton button) { //_CODE_:button1:12356:
     // It is safe to enter your event code here  
 } //_CODE_:button1:12356:
 
 * Do not rename this tab!
 * =========================================================
 */

synchronized public void win_draw1(GWinApplet appc, GWinData data) { //_CODE_:window1:663785:
  appc.background(230);
} //_CODE_:window1:663785:

public void NumImagesSlider_change1(GSlider source, GEvent event) { //_CODE_:NumImagesSlider:859375:
  NumImages = source.getValueI();
  ReDraw = true;
  //println("NumImagesSlider - GSlider >> GEvent." + event + " @ " + millis());
} //_CODE_:NumImagesSlider:859375:

public void OffsetSlider_change1(GSlider source, GEvent event) { //_CODE_:OffsetSlider:244278:
  Offset = source.getValueF();
  ReDraw = true;
  //println("OffsetSlider - GSlider >> GEvent." + event + " @ " + millis());
} //_CODE_:OffsetSlider:244278:

public void NumCyclesSlider_change1(GSlider source, GEvent event) { //_CODE_:NumCyclesSlider:258930:
  NumCycles = source.getValueF();
  ReDraw = true;
  //println("NumCyclesSlider - GSlider >> GEvent." + event + " @ " + millis());
} //_CODE_:NumCyclesSlider:258930:

public void ThicknessSlider_change1(GSlider source, GEvent event) { //_CODE_:ThicknessSlider:836097:
  Thickness = source.getValueF();
  ReDraw = true;
  //println("ThicknessSlider - GSlider >> GEvent." + event + " @ " + millis());
} //_CODE_:ThicknessSlider:836097:

public void BlockStartSlider_change1(GSlider source, GEvent event) { //_CODE_:BlockStartSlider:831251:
  BlockStart = source.getValueF();
  ReDraw = true;
  //println("BlockStartSlider - GSlider >> GEvent." + event + " @ " + millis());
} //_CODE_:BlockStartSlider:831251:

public void BlockThicknessSlider_change1(GSlider source, GEvent event) { //_CODE_:BlockThicknessSlider:502892:
  BlockThickness = source.getValueF();
  ReDraw = true;
  //println("BlockThicknessSlider - GSlider >> GEvent." + event + " @ " + millis());
} //_CODE_:BlockThicknessSlider:502892:

public void MergingSlider_change1(GSlider source, GEvent event) { //_CODE_:MergingSlider:993263:
  MergeCount = source.getValueI();
  ReDraw = true;
  //println("MergingSlider - GSlider >> GEvent." + event + " @ " + millis());
} //_CODE_:MergingSlider:993263:

public void BlockCheckbox_clicked1(GCheckbox source, GEvent event) { //_CODE_:BlockCheckbox:828959:
  IncludeBlock = source.isSelected();
  ReDraw = true;
  //println("checkbox ival = "+source.isSelected());
  //println("BlockCheckbox - GCheckbox >> GEvent." + event + " @ " + millis());
} //_CODE_:BlockCheckbox:828959:



// Create all the GUI controls. 
// autogenerated do not edit
public void createGUI(){
  G4P.messagesEnabled(false);
  G4P.setGlobalColorScheme(GCScheme.BLUE_SCHEME);
  G4P.setCursor(ARROW);
  if(frame != null)
    frame.setTitle("Sketch Window");
  window1 = new GWindow(this, "Window title", 0, 0, 580, 450, false, JAVA2D);
  window1.addDrawHandler(this, "win_draw1");
  NumImagesSlider = new GSlider(window1.papplet, 20, 20, 310, 50, 10.0);
  NumImagesSlider.setShowValue(true);
  NumImagesSlider.setShowLimits(true);
  NumImagesSlider.setLimits(300, 50, 500);
  NumImagesSlider.setShowTicks(true);
  NumImagesSlider.setNumberFormat(G4P.INTEGER, 0);
  NumImagesSlider.setOpaque(true);
  NumImagesSlider.addEventHandler(this, "NumImagesSlider_change1");
  label1 = new GLabel(window1.papplet, 340, 20, 120, 50);
  label1.setTextAlign(GAlign.LEFT, GAlign.MIDDLE);
  label1.setText("Number of Images");
  label1.setTextBold();
  label1.setOpaque(false);
  OffsetSlider = new GSlider(window1.papplet, 20, 80, 310, 50, 10.0);
  OffsetSlider.setShowValue(true);
  OffsetSlider.setShowLimits(true);
  OffsetSlider.setLimits(0.0, 0.0, 1.0);
  OffsetSlider.setShowTicks(true);
  OffsetSlider.setNumberFormat(G4P.DECIMAL, 2);
  OffsetSlider.setOpaque(true);
  OffsetSlider.addEventHandler(this, "OffsetSlider_change1");
  NumCyclesSlider = new GSlider(window1.papplet, 20, 140, 310, 50, 10.0);
  NumCyclesSlider.setShowValue(true);
  NumCyclesSlider.setShowLimits(true);
  NumCyclesSlider.setLimits(1.0, 0.1, 5.0);
  NumCyclesSlider.setShowTicks(true);
  NumCyclesSlider.setNumberFormat(G4P.DECIMAL, 2);
  NumCyclesSlider.setOpaque(true);
  NumCyclesSlider.addEventHandler(this, "NumCyclesSlider_change1");
  ThicknessSlider = new GSlider(window1.papplet, 20, 200, 310, 50, 10.0);
  ThicknessSlider.setShowValue(true);
  ThicknessSlider.setShowLimits(true);
  ThicknessSlider.setLimits(1.0, 0.1, 5.0);
  ThicknessSlider.setShowTicks(true);
  ThicknessSlider.setNumberFormat(G4P.DECIMAL, 2);
  ThicknessSlider.setOpaque(true);
  ThicknessSlider.addEventHandler(this, "ThicknessSlider_change1");
  label2 = new GLabel(window1.papplet, 340, 80, 120, 50);
  label2.setTextAlign(GAlign.LEFT, GAlign.MIDDLE);
  label2.setText("Offset");
  label2.setTextBold();
  label2.setOpaque(false);
  label3 = new GLabel(window1.papplet, 340, 140, 120, 50);
  label3.setTextAlign(GAlign.LEFT, GAlign.MIDDLE);
  label3.setText("Number of Cycles");
  label3.setTextBold();
  label3.setOpaque(false);
  label4 = new GLabel(window1.papplet, 340, 200, 120, 50);
  label4.setTextAlign(GAlign.LEFT, GAlign.MIDDLE);
  label4.setText("Thickness");
  label4.setTextBold();
  label4.setOpaque(false);
  BlockStartSlider = new GSlider(window1.papplet, 20, 260, 310, 50, 10.0);
  BlockStartSlider.setShowValue(true);
  BlockStartSlider.setShowLimits(true);
  BlockStartSlider.setLimits(0.5, 0.0, 1.0);
  BlockStartSlider.setShowTicks(true);
  BlockStartSlider.setNumberFormat(G4P.DECIMAL, 2);
  BlockStartSlider.setLocalColorScheme(GCScheme.ORANGE_SCHEME);
  BlockStartSlider.setOpaque(true);
  BlockStartSlider.addEventHandler(this, "BlockStartSlider_change1");
  BlockThicknessSlider = new GSlider(window1.papplet, 20, 320, 310, 50, 10.0);
  BlockThicknessSlider.setShowValue(true);
  BlockThicknessSlider.setShowLimits(true);
  BlockThicknessSlider.setLimits(0.5, 0.0, 1.0);
  BlockThicknessSlider.setShowTicks(true);
  BlockThicknessSlider.setNumberFormat(G4P.DECIMAL, 2);
  BlockThicknessSlider.setLocalColorScheme(GCScheme.ORANGE_SCHEME);
  BlockThicknessSlider.setOpaque(true);
  BlockThicknessSlider.addEventHandler(this, "BlockThicknessSlider_change1");
  MergingSlider = new GSlider(window1.papplet, 20, 380, 310, 50, 10.0);
  MergingSlider.setShowValue(true);
  MergingSlider.setShowLimits(true);
  MergingSlider.setLimits(1, 1, 50);
  MergingSlider.setShowTicks(true);
  MergingSlider.setNumberFormat(G4P.INTEGER, 0);
  MergingSlider.setLocalColorScheme(GCScheme.RED_SCHEME);
  MergingSlider.setOpaque(true);
  MergingSlider.addEventHandler(this, "MergingSlider_change1");
  label5 = new GLabel(window1.papplet, 340, 260, 120, 50);
  label5.setTextAlign(GAlign.LEFT, GAlign.MIDDLE);
  label5.setText("Block Start");
  label5.setTextBold();
  label5.setLocalColorScheme(GCScheme.ORANGE_SCHEME);
  label5.setOpaque(false);
  label6 = new GLabel(window1.papplet, 340, 320, 120, 50);
  label6.setTextAlign(GAlign.LEFT, GAlign.MIDDLE);
  label6.setText("Block Thickness");
  label6.setTextBold();
  label6.setLocalColorScheme(GCScheme.ORANGE_SCHEME);
  label6.setOpaque(false);
  label7 = new GLabel(window1.papplet, 340, 380, 120, 50);
  label7.setTextAlign(GAlign.LEFT, GAlign.MIDDLE);
  label7.setText("Merging");
  label7.setTextBold();
  label7.setLocalColorScheme(GCScheme.RED_SCHEME);
  label7.setOpaque(false);
  BlockCheckbox = new GCheckbox(window1.papplet, 470, 260, 100, 50);
  BlockCheckbox.setTextAlign(GAlign.LEFT, GAlign.MIDDLE);
  BlockCheckbox.setText("Include Block");
  BlockCheckbox.setTextBold();
  BlockCheckbox.setLocalColorScheme(GCScheme.ORANGE_SCHEME);
  BlockCheckbox.setOpaque(true);
  BlockCheckbox.addEventHandler(this, "BlockCheckbox_clicked1");
}

// Variable declarations 
// autogenerated do not edit
GWindow window1;
GSlider NumImagesSlider; 
GLabel label1; 
GSlider OffsetSlider; 
GSlider NumCyclesSlider; 
GSlider ThicknessSlider; 
GLabel label2; 
GLabel label3; 
GLabel label4; 
GSlider BlockStartSlider; 
GSlider BlockThicknessSlider; 
GSlider MergingSlider; 
GLabel label5; 
GLabel label6; 
GLabel label7; 
GCheckbox BlockCheckbox; 

End of post.

«1

Answers

  • I've got some NPEs in this line too: label1 = new GLabel(window1.papplet, 340, 20, 120, 50);.
    Inserted a delay(100); before it and the NPE never show up anymore! B-)

  • I'm very glad you could reproduce the problem. And that's a very clever solution! Thank you! But I intend to hand out this program to students as a scaffold for their own projects. So while this practical solution seems to also work on my computer, it doesn't prevent the problem from potentially re-appearing on other computers that might have different timing issues.

    Building on your suggestion, I just tried inserting a whole bunch of tests into gui.pde so that it delays building objects until window1 is non-null, and then it delays exiting createGUI() until all the UI objects are non-null, but I still get errors.

    I'd really like to find a solution that identifies and addresses the problem, so I know it can't happen again.

  • For comparison, my getStackTrace(): :-B

    java.lang.NullPointerException
        at g4p_controls.StyledString.getLines(Unknown Source)
        at g4p_controls.GLabel.updateBuffer(Unknown Source)
        at g4p_controls.GLabel.draw(Unknown Source)
        at g4p_controls.GWindowInfo.draw(Unknown Source)
        at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1240)
        at processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1233)
        at processing.core.PApplet.handleMethods(PApplet.java:1427)
        at processing.core.PApplet.handleDraw(PApplet.java:2405)
        at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:245)
        at processing.core.PApplet.run(PApplet.java:2260)
        at java.lang.Thread.run(Unknown Source)
    
  • Thanks! You got one call deeper into the mystery.

  • Unfortunately I am unable to reproduce the error but I suspect that I know the cause.

    In line 5 of the stacktrace it shows that the NPE is generated in the window draw method, basically it is try to do this before the controls are ready.

    So try this

    Move this line (82)

    window1.addDrawHandler(this, "win_draw1");

    so it becomes the last line in createGUI method. Careful because this change will be overwritten if you launch GUI Builder again.

  • edited May 2015

    Thanks! I just moved that line to the end, but no change. I'm still getting both types of errors. Here's the new stack for the NPE:

    java.lang.NullPointerException
        at g4p_controls.StyledString.getLines(Unknown Source)
        at g4p_controls.GLabel.updateBuffer(Unknown Source)
        at g4p_controls.GLabel.draw(Unknown Source)
        at g4p_controls.GWindowInfo.draw(Unknown Source)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1236)
        at processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1229)
        at processing.core.PApplet.handleMethods(PApplet.java:1423)
        at processing.core.PApplet.handleDraw(PApplet.java:2401)
        at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:240)
        at processing.core.PApplet.run(PApplet.java:2256)
        at java.lang.Thread.run(Thread.java:745)
    

    And here's the stack when I get a CME:

    java.util.ConcurrentModificationException
        at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:953)
        at java.util.LinkedList$ListItr.next(LinkedList.java:886)
        at g4p_controls.GLabel.updateBuffer(Unknown Source)
        at g4p_controls.GLabel.draw(Unknown Source)
        at g4p_controls.GWindowInfo.draw(Unknown Source)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1236)
        at processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1229)
        at processing.core.PApplet.handleMethods(PApplet.java:1423)
        at processing.core.PApplet.handleDraw(PApplet.java:2401)
        at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:240)
        at processing.core.PApplet.run(PApplet.java:2256)
        at java.lang.Thread.run(Thread.java:745)
    

    It doesn't always highlight a line after the crash, but when it does it's the line beginning label1 = new GLabel. I also tried putting a delay(100) just before the new last line (setting the draw handler) as per GoToLoop's suggestion, but it's still crashing upon launch most of the time. A friend of mine on a PC has tried running this code and it's also crashing for him most of the time.

    I noticed that when it highlights a line upon crashing, it's always the line where label1 is created (which doesn't exactly match the stack, which is telling us there's a problem when the window gets drawn - another mystery). I thought maybe there's a thread synchronization problem specific to labels, so I tried moving all the label code to the top of createGUI (after the creation of window1, of course, and with the draw handler assignment moved to the end, per Quark's advice). This also failed with an NPE, but with a stack trace unlike the ones I've been getting so far. In the hopes that this might be illuminating, I'm pasting that here:

    java.lang.NullPointerException
        at java.lang.System.arraycopy(Native Method)
        at sun.awt.image.IntegerInterleavedRaster.setDataElements(IntegerInterleavedRaster.java:429)
        at processing.core.PGraphicsJava2D$ImageCache.update(PGraphicsJava2D.java:1484)
        at processing.core.PGraphicsJava2D.imageImpl(PGraphicsJava2D.java:1301)
        at processing.core.PGraphics.image(PGraphics.java:3575)
        at processing.core.PApplet.image(PApplet.java:12773)
        at g4p_controls.GLabel.draw(Unknown Source)
        at g4p_controls.GWindowInfo.draw(Unknown Source)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1236)
        at processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1229)
        at processing.core.PApplet.handleMethods(PApplet.java:1423)
        at processing.core.PApplet.handleDraw(PApplet.java:2401)
        at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:240)
        at processing.core.PApplet.run(PApplet.java:2256)
        at java.lang.Thread.run(Thread.java:745)
    

    I'd be happy to try any other experiments to fix this. I'd love to use G4P in this project, but I can't hand out code that usually won't run!

  • The difficulty I am having is replicating the problem. I have tested the code on OSX 10.9.5 and 10.10.3 and the program works as expected.

    Each GWindows runs in a separate thread so this can cause CME errors if the user is not careful. I can see no problem in this case.

    The NPE is almost certainly caused by the secondary window not being ready when the control is being created, in which case the modification suggested by GoToLoop will work and won't generate any errors in itself. Why it shouldn't be ready is a mystery unless the program is being split over multiple processor cores.

    Try changing line 90 to

    label1 = new GLabel(this, 340, 20, 120, 50);

    the label should appear on the main display but I would be interested in knowing what error messages (if any) you get.

  • Thanks, Quark. This sure feels like some kind of timing issue - I'm on an iMac with a 3.5 GHz Intel Core i5. The Mac is no doubt shuffling threads among cores internally, but out of my control. Note that GoToLoop and my friend have both replicated the error (I don't know what computer GoToLoop used, but my friend's on a PC), so it's not just my machine.

    I went back to the original version of the code (posted in my first message, so the draw handler is added immediately after window1 is made) and made the latest change you suggested. I ran the program about 20 times, and it never crashed, which is a new world record! The really weird thing is that I left all the other lines exactly the same, so the only change is that label1 is going to the main PApplet, while all the other labels and controls are going to the new window's applet.

    I'm a little nervous about the delay(100) solution because, while it seems to work, maybe on one of my student's computers that delay won't be long enough (and I don't want them to have to mess with this!). To try to be more robust about it, I put these lines right before the label1 constructor, but they didn't help - I still get the same crashes with roughly the same stack trace:

    while (window1 == null) delay(100);
    while (window1.papplet == null) delay(100);
    

    Is there any principled way to get things to wait until their necessary preconditions are satisfied?

  • Answer ✓

    Try this

    change the label code back so that it appears in the secondary window then move the 5 lines that create and set label1 so they appear after the sliders i.e between lines 118 & 119 just infornt of the label2 code and see what happens.

    I think GoToLoop uses a Linux machine.

    100ms is an age for a computer so it should long enough, if in doubt change it to 250ms after all it is just a one off delay so wont affect the running program.

    Also the 2 while loops can be made into 1

    while (window1 == null || window1.papplet == null) delay(100);

    • My main Linux desktop machine is lacking a fan, so I can't use it until I put another! :-&
    • For now, just using a Win8.1 laptop. And a crap i3 380M @ 2.53 GHz.
    • And I need to re-run about 10 times in order to get an NPE. Never had any CMEs though.
    • There are times I can never make it crash unless I've got some heavy app messing w/ the computer overall performance! 3:-O
    • That while (window1 == null || window1.papplet == null) delay(100); is useless.
    • B/c those errors are happening inside G4P library and papplet is perfectly initialized w/ this a long time ago. :-@
    • Since there are more than 1 Thread running at the same time, any highlighted error line is merely where the main "Animation" Thread was at the moment the other problematic Thread had NPEs or CMEs.
  • Quark: Moving the lines doesn't help. I also tried consolidating all of the labels at the end, also to no benefit. The really weird thing is that this seems specific to labels only - the stack trace always includes a call to GLabel.draw(), and never any of the other UI objects, even if I move around the order in which they're created. When I comment out all the labels, it also works fine.

    GoToLoop: Thanks for the comments! I didn't know about the highlighting behavior in the presence of multiple threads, but of course your explanation makes perfect sense.

    It's mysterious to me that this code fails while Quark's examples in the library download run fine, every time. But the delay just before making label1 does seem to make the crashes stop, so I'll mark that as the answer to this question. Here's hoping the crashes stay gone!

    Thank you both for your help with this. I appreciate it very much!

  • edited May 2015
    java.lang.NullPointerException
        at g4p_controls.StyledString.getLines(Unknown Source)
        at g4p_controls.GLabel.updateBuffer(Unknown Source)
    
    • After perusing the G4P library, for that error to throw, field StyledString's stext from class GTextBase gotta be null.
    • However, I can't see how that could ever happen since it's declared and initialized at the same line:
      protected StyledString stext = new StyledString("");
    • And I couldn't spot any other place where stext might be assigned to null either!

    java.util.ConcurrentModificationException
        at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:953)
        at java.util.LinkedList$ListItr.next(LinkedList.java:886)
        at g4p_controls.GLabel.updateBuffer(Unknown Source)
    
    • In order to reach updateBuffer()'s for(TextLayoutInfo lineInfo : lines) code line,
      LinkedList<TextLayoutInfo> lines = stext.getLines(g2d); gotta be successful.
    • This time, stext isn't null for a change! :D
    • The only way I see for that CME now is when another Thread would be invoking the same GLabel's updateBuffer() at the same time the for ( : ) is busy.
    • B/c it would change lines' LinkedList immediately after a concurrrent call to getLines().
    • But I can't envision how more than 1 Thread would be invoking updateBuffer() for the same GLabel almost at the same time... :-??
  • Terrific detective work! But I already marked this as answered, so I'm not sure if Quark is looking at this thread any more. Is there a way to mark it as unanswered, or otherwise get his attention to take your analysis and perhaps find/fix what's going on?

  • edited May 2015
    • There's no way to unmark anything I'm afraid! ~:>
    • But no worries, answerers here not even notice what is the current status of forum threads.
    • We always take another look, especially when we're participating on it! =P~
    • Since I've got no much experience w/ analyzing stack traces, I believe I've made a mistake...
    • I'm starting to think that something like:at g4p_controls.StyledString.getLines(Unknown Source)
      doesn't necessarily mean it happened when the program tried to invoke the method.
    • Rather it's already inside and the Exception happened at some other unspecified code line there!
    • Therefore, it wasn't b/c stext was null.
    • But rather another variable inside getLines() was null! b-(
  • @GoToLoop thanks for investigating this problem. As you have discovered stext cannot be null because it is created when the label is instantiate and it is never set to null. Which means I don't understand

    • This time, stext isn't null for a change! :D

    Have I missed something in the code?

    The updateBuffer method is ONLY called from the controls draw() method.

    Basically as of V3 of this library all controls are draw to a graphics buffer and then this buffer is draw to the main screen. The reason was to ensure that rendering and in particular text rendering looked good in any of Processing's renderers.

    When something happens that involves a change in the controls appearance occurs then the bufferInvalid variable is set to true. This is picked up in the updateBuffer method. It makes G4P more CPU friendly at the cost of some RAM for the buffers.

    Processing takes over the Java's main event thread to provide simple event handling methods for the programmer. Unfortunately it made it difficult for me to implement multiple windows and I had to make major changes when Processing went to V2 because of the changes in Processing.

    The main class is the GWindowInfo class. It is responsible for adding/removing G4P controls (e.g. GLabel) to instances of GWindow It is also forwards events to the controls in that window.

    Anyway I will investigate this further but it will be difficult to find a solution if I can't reproduce the error, I will just have to do it by code examination. Unfortunately I won't be able to start for a few days because I am busy.

  • edited May 2015

    Which means I don't understand: This time, stext isn't null for a change!

    Due to my lack of experience, I still believed that at g4p_controls.StyledString.getLines(Unknown Source)
    meant that the program crashed while trying to invoke getLines().

    As you have discovered stext cannot be null...

    Yup! And it puzzled me even more since getLines() by logic would never crash! :@)
    Now I understand that the NPE happened somewhere inside getLines()! 8-|

  • @GoToLoop Thanks for the clarification

    @Floritude I know the forum bugs you to Accept or Reject answers but you don't have to do either. Only use Accept when the problem has been solved. Ignore the Reject unless the comment is off topic.

  • @Quark: If I can run something on my computer to gather information that would help you analyze the problem, I'd be happy to do so (I'd need your instructions for just what to do, though!).

  • edited May 2015
    • I've got a hypothesis about what could possibly trigger those ephemeral bugs! :-B
    • I guess it lies inside GLabel's constructor:

    public GLabel(PApplet theApplet, float p0, float p1, float p2, float p3, String text) {
        super(theApplet, p0, p1, p2, p3);
        setText(text);
        opaque = false;
        // Now register control with applet
        registeredMethods = DRAW_METHOD;
        G4P.addControl(this);
        bufferInvalid = true;
        updateBuffer();
    }
    
    • As we all have noticed, updateBuffer() was always a constant in both NPE & CME stack traces too!
    • After registering the newly created GLabel object here: G4P.addControl(this);
    • The constructor then invokes updateBuffer().
    • I wonder whether G4P's Thread is already accessing the newborn GLabel and invoking updateBuffer() right after the constructor is concurrently busy doing the same! :-t
    • If I'm correct, it's enough to cut & paste bufferInvalid = true; updateBuffer();
      before G4P.addControl(this); O:-)
    • It's all based on my previous guess. Tee-hee: :bz

    The only way I see for that CME now is when another Thread would be invoking the same GLabel's updateBuffer() at the same time the for ( : ) is busy.

  • @GoToLoop sounds logical I will investigate that possibility first.

    @Floritude yes you will be able to help because I can't test potential solutions as I can't replicate the errors. When I think I have a solution then I will post a link to a modified library zip file which you will need to install manually.

    I will post the link in this discussion so it will be available to you and GoToLoop.

    As I said bit busy now so probably next weekend.

  • edited May 2015

    IMO, even if it isn't the desired fix, I think it makes more sense & it's safer to have the object fully initialized before registering it! ~O)

  • edited May 2015 Answer ✓

    I have just tried the suggestion from @GoToLoop and moved the two lines. The modified library can be downloaded here

    Please try it out and let me know how you get on. :)

  • Wow! That was fast! Thx! ^:)^

  • Replaced the original "G4P.jar" w/ your latest 1 and I've failed miserably in getting even 1 single NPE again! \m/
    Even before I had to put the laptop in stress by running some heavy app while re-running the sketch many times.
    I'm pretty sure it's fully fixed on my side here! Congratz! $-)

  • edited May 2015

    But I'd still advise, for precaution's sake, to check other constructors where the same problem might arise, when you've got more spare time! #:-S

  • Wow! That seems to have fixed it! I just ran the code from my first post (no delay, no moving of lines) and it worked perfectly 30 times in a row. I think that fixes it!

    This is a really big deal for me, as it means I can get back to working on my program and eventually provide it to students, without the worry that there's a bug out there waiting to (sometimes) cause a crash.

    I am very grateful for your individual and combined efforts. I hope I'm able to fix problems with my own library as quickly and efficiently, and in as friendly and professional a manner, as you have done. You guys are great. Thank you!

  • @GoToLoop that was a fine bit of detective work and has saved me a lot of work trawling through the source code trying to find a problem that I couldn't reproduce. I am pretty certain it is the only constructor that called these methods because I sort of remember putting them in as a hack when I was working on another issue, but I will check before the next version release. Thanks very much for your help.

    I can't do anything now until but I will make the changes permanent and check the other ctors. I will release the new version this coming weekend and it will become available through the PDE then.

    @Floritude I am glad you like G4P and GUI Builder. G4P was my first library released in 2009 with regular bug fixes so is normally very reliable but if you get further problems post a question in this forum and send me a PM so I get an email notification. :D

  • edited May 2015

    I am pretty certain it is the only constructor that called these methods...

    I've meant those constructors who would follow the same "model".
    That is, registering as control in the middle rather than being the final thing.
    Saying this b/c I only checked GLabel and its parent classes.

  • Don't worry I will check all the ctors before the next release

    Thanks again

  • Hi, I have reported this error as well on Sourceforge according to project specs.

    It is in every constructor and on Java 8 it throws NPE everytime. Due to this I cannot run my sketch on Java 8 for ARM and Processing 3 on Linaro (Ubuntu ARM). I have my gig on a Friday as a headliner (Cyberluke DJ/producer). Do you think that the new release will be saaay...today?? :-D

  • Also none of your examples is working because of this...when put G4P out of my way, it runs great on ARM (and after upgrading java serial lib in Processing, which contains arm native libs in it).

  • @cyberluke

    I tried G4P on earlier versions of Processing 3 (3.0.a4) and it worked . I just tried on 3.0a9 and it didn't work throwing NPE errors

    I have no intention of modifying any of my libraries and tools until the official release of V3. When Processing moved to V2 trying to keep up with the alpha releases was a nightmare and I am not going through that again.

    I will be maintaining them for 2.2.1 so I suggest that you use Processing 2.2.1

    The library I modified for testing can be downloaded here it solved the problem for 2.2.1

  • edited May 2015
    • I use v3.0a5 since it's the last version which is still based on Applet class.
    • It's very stable even more than 2.2.1. And all libraries work AFAIK.
    • For "Python Mode", I've heard latest compatible version is 3.0a4 though.
    • And as I already warned many times, stay away from anything past v3.0a5.
    • As a regular answerer here, I won't aid any1 using latest 3 alpha versions until a stable version arrives!
  • I have just released G4P V3.5.3 which solves this problem for Processing V2.2.1

    It should be available through the PDE add library option.

  • Well, this is unfortunate: I'm still getting the occasional startup crash. As before, the problems are always at startup, and happen unpredictably: the program will run fine 20 times in a row, then crash 3 times in a row, then run again, and so on.

    My code has changed, but it's really just more of the same from before: a sequence of UI builders and a bunch of handlers that just set global variables. There's much more to the program now, but I can strip it down to the UI part and post that (but even that is very long). I'm still using Processing 2.2.1 on the Mac, and this afternoon I deleted my copy of G4P and used the Library Manager to install a fresh one (which I understand from the messages above includes the recent fix).

    Here's the report from one crash:

    java.lang.NullPointerException
        at java.util.LinkedList$ListItr.next(LinkedList.java:891)
        at g4p_controls.GTextField.updateBuffer(Unknown Source)
        at g4p_controls.GTextField.draw(Unknown Source)
        at g4p_controls.GWindowInfo.draw(Unknown Source)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1236)
        at processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1229)
        at processing.core.PApplet.handleMethods(PApplet.java:1423)
        at processing.core.PApplet.handleDraw(PApplet.java:2401)
        at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:240)
        at processing.core.PApplet.run(PApplet.java:2256)
        at java.lang.Thread.run(Thread.java:745)
    

    And a different kind of report from another startup crash (this text was printed to the output window in white, not red):

    ################  EXCEPTION IN EVENT HANDLER  ################
    An error occured during execution of the eventhandler:
    CLASS: Project323_v2   METHOD: WindowSculpture_draw1
        Caused by java.util.ConcurrentModificationException
        java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
        java.util.ArrayList$Itr.next(ArrayList.java:831)
        Project323_v2.WindowSculpture_draw1(Project323_v2.java:1199)
        sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        java.lang.reflect.Method.invoke(Method.java:606)
        g4p_controls.GWinApplet.draw(Unknown Source)
        processing.core.PApplet.handleDraw(PApplet.java:2386)
        processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:240)
        processing.core.PApplet.run(PApplet.java:2256)
        java.lang.Thread.run(Thread.java:745)
    ##############################################################
    
  • You also sent a PM which I responded before seeing this last comment.

    I will PM you with my email address. and if you archive the full sketch (use the Tools menu option) and send it to me as an attachment I will have a look at it and see if I can reproduce the problem.

  • edited May 2015

    (which I understand from the messages above includes the recent fix)

    In my own Processing v3.0a5, the available GP4 library is still the old & bugged v3.5.2! 3:-O
    Of course in my case, I've already replaced the original "/library/G4P.jar" w/ the 1 from:
    http://www.lagers.org.uk/temp/G4P.zip since that day! O:-)

  • edited May 2015

    I downloaded G4P 3.5.3 from the PDE with 2.2.1 about an hour ago.

    Delete the existing G4P library and try again. It is also available from SourceForge

  • edited May 2015

    @quark, G4P 3.5.3 update is still not available for me! :(
    Even after deleting G4P and Processing's "contributions.txt", available version is the old 3.5.2.
    The re-downloaded "contributions.txt" is always the same v3.5.2!!! :(

    "contributions.txt"'s excerpt:

    library category=GUI minRevision=0 authorList=[Peter Lager](http://www.lagers.org.uk) name=G4P maxRevision=0 sentence=Provides a set of 2D GUI controls and multiple window support. url=http://www.lagers.org.uk/g4p prettyVersion=3.5.2 paragraph=Controls include buttons, sliders, knobs, labels, textfields, timers, combo boxes, option buttons etc. and multiple windows. [G4P GUI builder](http://www.lagers.org.uk/g4ptool/index.html) is a companion tool that enables the rapid (visual) development of user interfaces with this library. version=20 download=http://www.lagers.org.uk/processing/g4p/G4P.zip id=051

  • edited May 2015

    Never mind! Even though "contributions.txt" thinks the latest version is still 3.5.2,
    if we uninstall & then re-install it, it downloads again from: http://www.lagers.org.uk/processing/g4p/G4P.zip

    And it ends up getting the latest version after all. <:-P

    However, if we don't uninstall G4P, it will forever keep buggy v3.5.2 w/o we ever knowing there is a more updated version! :-&

  • @GoToLoop thanks for the info decided to check everything out my end.

    I have no ides why the contributions manager it is not recognising the new version.

    The library.properties file in the zip download correctly identifies the version as 21 and 3.5.3 but this is not shown in the Processing/libraries/G4P folder which still reports it as 20 and 3.5.2

    I believe this might be a bug in the contributions manager perhaps @prisonerjohn might have a look into this.

    So for the moment it is important to DELETE the existing G4P installation before installing the new one.

    When you run a sketch using G4P it will show the version in the PDE console (black) panel, make sure it is 3.5.3

  • The version of G4P I'm using now, and used when I got the above errors, self-reports as 3.5.3.

  • @quark But, I need Processing 3a6. From this version it can be run with Java 8: https://raw.githubusercontent.com/processing/processing/master/build/shared/revisions.txt

    Java 7 is not supported nor updated anymore! http://www.oracle.com/technetwork/java/javase/eol-135779.html

    Don't know why Processing team felt asleep and wrote in official documentation that there is no need for Java 8 :-/

    So current state is that Processing 2 is running on outdated and unsupported End Of Live Java. Processing 3a6 from April 2015 is working, but your library is not working under it. You will have to fix it anyway :-D ...shame that Processing does not have any standard GUI library. Writing buttons in a standard way is a mess even for one-way beginner tasks, not to mention multi class projects.

    This whole project and G4P with NPE is such a mess, I will have to find something better...

  • edited May 2015
    • All Processing versions work w/ Java 8!
    • My own old v1.5.1 uses my system's installed 64-bit JDK 8 w/o any problems!
    • Simply export your sketches w/o any runtime and it's gonna run w/ the OS's installed Java.
  • @cyberluke it seems that @GoToLoop has the answer of using Processing 2.2.1 with G4P 3.5.3 and with Java 8 :D

    Many libraries like G4P will break because of the major changes made in PS moving from v2 to v3.

    I am not going to update G4P until we have a stable release for PS v3. Even then I will do nothing until we get some documentation from the developers on the changes.

  • edited May 2015

    Actually I'm using v3.0a5, which is the last 1 to inherit from Applet. ;))

  • OK 3.0a5 but the method you described should work with 2.2.1 ?

  • edited May 2015

    As mentioned, all Processing versions should work w/ Java 8 when exported w/o some bundled runtime!

  • edited May 2015

    I was not able to run Processing IDE v2 with Java 8. It crashed with some array implementation mismatch and some serial uuid. Now I tried it on Windows8 x64 and it looks working. On Ubuntu ARM this problem persists. So I have to run Processing 2 with Java 7 Embedded and Processing 3 with Java 8. I expect you will say that ARM is not your problem, but hey it's 2015 with wearables and Java 8 with lambdas :-) ...and you confirmed NPEs with Java 8, which is a very bad software behavior especially for a piece of code like reusable library this should be. If Processing IDE is for prototyping and artists, we need not the latest alpha version, but at least the latest technologies like Java 8, which is there for a while.

  • (one thing is running with JRE, other thing is compiling with JDK inside Processing IDE)

Sign In or Register to comment.