codenameone / CodenameOne

Cross-platform framework for building truly native mobile apps with Java or Kotlin. Write Once Run Anywhere support for iOS, Android, Desktop & Web.
https://www.codenameone.com/
Other
1.7k stars 405 forks source link

problem while building the initial screen #3013

Open ddyer0 opened 4 years ago

ddyer0 commented 4 years ago

This error (and others like it) occurs occasionally when assembling the initial screen as the app is launched. The relevant point in the backtrace is the .add(..) operation, which ought not fail.

error is : java.lang.IllegalStateException: This method should not be invoked by external code! [launcher] 0:0:0,0 - Exception: java.lang.IllegalStateException - This method should not be invoked by external code! java.lang.IllegalStateException: This method should not be invoked by external code! at com.codename1.ui.util.EventDispatcher$CallbackClass.run(EventDispatcher.java:85) at com.codename1.ui.Display.callSerially(Display.java:845) at com.codename1.ui.util.EventDispatcher.fireSelectionEvent(EventDispatcher.java:409) at com.codename1.ui.list.DefaultListModel.setSelectedIndex(DefaultListModel.java:198) at com.codename1.ui.List.initComponentImpl(List.java:329) at com.codename1.ui.Container.initComponentImpl(Container.java:1132) at com.codename1.ui.Container.initComponentImpl(Container.java:1132) at com.codename1.ui.Container.initComponentImpl(Container.java:1132) at com.codename1.ui.Container.insertComponentAtImpl(Container.java:853) at com.codename1.ui.Container.insertComponentAt(Container.java:817) at com.codename1.ui.Container.addComponent(Container.java:739) at com.codename1.ui.Container.add(Container.java:358) at bridge.Container.supadd(Unknown Source) at bridge.Container.access$000(Unknown Source) at bridge.Container$1.run(Unknown Source) at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:95) at com.codename1.ui.Display.callSerially(Display.java:845) at com.codename1.ui.Display.callSeriallyAndWait(Display.java:934) at bridge.Platform.runInEdt(Unknown Source) at bridge.Container.add(Unknown Source) at bridge.Frame.setContentPane(Unknown Source) at util.PasswordCollector.createAndShowGUI(Unknown Source) at util.Login.initFromWebStart(Unknown Source) at util.JWSApplication.runLogin(Unknown Source) at util.JWSApplication.runMain(Unknown Source) at util.JWSApplication.runLobby(Unknown Source) at com.boardspace.BoardspaceLauncher.launchLobby(Unknown Source) at com.boardspace.BoardspaceLauncher.doit(Unknown Source) at com.boardspace.BoardspaceLauncher.run(Unknown Source) at java.lang.Thread.run(Thread.java:761)

shannah commented 4 years ago

Looks like this code is run before Codename One is initialized (Display.init()), so the EDT isn't fired up yet.

ddyer0 commented 4 years ago

Calling Display.init() isn't part of my app. The code in question is run from the start() method

public void start() {
    Http.setHostName(connectHost);
    //no longer needed as of 5/2017
    //G.namedClasses = NamedClasses.classes;
    G.setGlobalStatus(G.GlobalStatus.awake);
    if (current != null) 
    {   G.print("Launcher restart "+new BSDate().toString());
        current.show();
        return;
    }
    G.print("Launcher start "+new BSDate().toString());
    runBoardspace();

}
ddyer0 commented 4 years ago

I suppose it might be the case that there's a race between the EDT getting running and this process, but you can see it is running under CallSeriallyAndWait, so whatever synchronization might be needed is on you.

shannah commented 4 years ago

That stack trace doesn't look like it came from our simulator, or any of our device builds, or any of our desktop builds. I.e. you've built your own bootstrap. You should take a look at the output of a Desktop build to see the housekeeping you'll need to make a launcher. Bare minimum, CN1 must be initialized (via Display.init()) before it can be used.

shannah commented 4 years ago

Am I wrong about you doing your own bootstrapping here?

ddyer0 commented 4 years ago

You're wrong. I started with the Launch class provided by the application wizard. This is a very occasional problem starting up, 99% of the time it has no glitches.

ddyer0 commented 4 years ago

Some other bits: it's happening with a variety of client hardware. I can't swear that it never happened before your recent changes to repaint/layout, but it's the kind of thing I would have noticed in my logs if it had. So my best guess is that it has something to do with the timing of the initial paint() operation.

shannah commented 4 years ago

Where is that thread started? (the one shown in the stack trace)?

ddyer0 commented 4 years ago

First occurred on 1/15, the log file that contains 1/15/2020 goes back to 10/14/2019, 9 occurrences since 1/15

ddyer0 commented 4 years ago

here's Lanch.java

package com.boardspace;
import lib.BSDate;
import lib.G;
import lib.Http;
import lib.NullLayout;
import online.common.OnlineConstants;
import util.JWSApplication;
import vnc.UDPService;
import bridge.Color;
import bridge.Frame;
import bridge.FullScreen;
import bridge.Panel;
import bridge.Config;

import com.codename1.io.Log;
import com.codename1.ui.Display;
import com.codename1.ui.Form;
import com.codename1.ui.Graphics;
import com.codename1.ui.Image;
import com.codename1.ui.plaf.UIManager;
import com.codename1.ui.util.Resources;

interface stuff {
    public String connectHost = "boardspace.net" ; //;
    public String serverHost = "boardspace.net";
    public String developHost = "192.168.0.2";
    public String game = "arimaa";
    public String viewer = "arimaa.ArimaaViewer";
    public String dir = "file:file://g:/share/projects/boardspace-html/htdocs/arimaa/arimaagames/";
    public boolean launchLobby = true;
    public boolean console = true;
    public boolean debug = false;   // for development version only
}

class Splash extends Panel implements FullScreen,Runnable,Config
{   Image splash ;
    Frame frame;

    public Splash(Image im) 
    { splash = im;
      frame = new Frame(); 
      frame.setLayout(new NullLayout(frame));
      frame.add(this);
    }

    public void paint(Graphics gr)
    {   int w = getWidth();
        int h = getHeight();
        G.setColor(gr,Color.gray);
        G.fillRect(gr,0,0,w,h);
        if(splash!=null) { G.centerImage(gr,splash, 0,0,w,h,null); }
    }
    public static void doSplash()
    {   Image splash = G.getImage(SPLASHSCREENIMAGE);
        if(splash==null) { G.infoBox("splash screen missing",SPLASHSCREENIMAGE); }
        Splash comp = new Splash(splash);
        comp.setVisible(true);
        new Thread(comp,"launcher").start();
    }

    @Override
    public void run() {
        frame.show();
        G.doDelay(10000);   
        frame.dispose();
    }
}

class BoardspaceLauncher implements Runnable,stuff
{   
    boolean develop = false;
    public BoardspaceLauncher(boolean dev) {develop=dev; }
    public void launchLobby()
    {   
        //test login window
        String params[] = new String[]
                {"servername",connectHost,
                 "develophost",developHost,
                 "development",""+develop,
                 "extraactions",""+develop,
                // "playtable","true",
                 G.DEBUG,""+develop,
                };
        util.JWSApplication.runLobby(params);
    }

    public void launchGame()
    {   
           //test login window
        String params[] = new String[]
                {"servername",connectHost,
                Config.PROTOCOL,(develop?"http":"https"),
                G.DEBUG,""+develop,
                OnlineConstants.EXTRAACTIONS,"true",
                OnlineConstants.EXTRAMOUSE,"true",
                OnlineConstants.GAMETYPE,game,
                OnlineConstants.VIEWERCLASS,viewer,
                OnlineConstants.REVIEWERDIR+"0",dir,
                //"playersingame","3",
                //"GameType","Exxit",
                //"viewerClass","exxit.ExxitGameViewer",

                //"GameType","Yspahan",
                //"viewerClass","yspahan.YspahanViewer",

                //"GameType","BreakingAway",
                //"viewerClass","breakingaway.BreakingAwayViewer",

                //"GameType","Arimaa",
                //"viewerClass","arimaa.ArimaaViewer",

                //"GameType","Hex",
                //"viewerClass","hex.HexGameViewer",

                //"GameType","Hive",
                //"viewerClass","hive.HiveGameViewer",

                //"GameType","Euphoria",
                //"viewerClass","euphoria.EuphoriaViewer",

                // "GameType","Kamisado",
                // "viewerClass","kamisado.KamisadoViewer",

                 //"GameType","Checkers-turkish",
                 //"viewerClass","checkerboard.CheckerGameViewer",

                //"GameType","Go-19",
                //"viewerClass","goban.GoViewer",
                //"reviewerdir0","file:///g:/share/projects/boardspace-html/htdocs/goban/gogames",

                "localfile","true",
                "randomseed","01234",
                "serverkey","1.2.3.4",
                "reviewonly","true",
                "final","true",

                };
        JWSApplication app = new JWSApplication();
        app.runMain(params); 

    }
    public void doit()
    {   Http.setHostName(connectHost);
        try {
            Log.setReportingLevel(Log.REPORTING_DEBUG);
            //MasterForm form = MasterForm.getMasterForm();
            //form.show();
            if(launchLobby)
                {
                boolean isTable = G.isPlaytable();
                // start the UDP service as soon as possible
                if(!G.getBoolean(Config.REVIEWONLY, false)) { UDPService.start(isTable); }  
                Splash.doSplash();
                launchLobby(); 
                } 
            else
                { launchGame(); }
        }
        catch (Throwable err)
        {G.printStackTrace(err);
         Http.postError(this,"outermost run",err);
        }
    }
    public void run() {
        doit(); 
    }
}

public class Launch implements stuff {
    Form current = null;
    public boolean isDevelopmentVersion() { return(false); }
    public void runBoardspace()
    {   if(console && isDevelopmentVersion()) { G.createConsole(); }
        new Thread(new BoardspaceLauncher(isDevelopmentVersion()),"launcher").start();
    }

    private static Resources res;
    public void init(Object context) {
        try {
            res = Resources.openLayered("/theme");
            UIManager.getInstance().setThemeProps(res.getTheme(res.getThemeResourceNames()[0]));
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    public void start() {
        Http.setHostName(connectHost);
        //no longer needed as of 5/2017
        //G.namedClasses = NamedClasses.classes;
        G.setGlobalStatus(G.GlobalStatus.awake);
        if (current != null) 
        {   G.print("Launcher restart "+new BSDate().toString());
            current.show();
            return;
        }
        G.print("Launcher start "+new BSDate().toString());
        runBoardspace();

    }

    public void stop() {
        current = Display.getInstance().getCurrent();
        G.setGlobalStatus(G.GlobalStatus.asleep);
        G.print("Launcher stop " +new BSDate().toString());
    }

    public void destroy() {
        current = Display.getInstance().getCurrent();
        G.setGlobalStatus(G.GlobalStatus.asleep);
        G.print("Launcher destroy "+new BSDate().toString());
    }

}

the actual run is in a method called "runBoardspace"

shannah commented 4 years ago

Is this only happening in simulator/desktop, or on devices also?

ddyer0 commented 4 years ago

So far, only on real android devices. I imagine with a good theory about the exact sequence of events, it would be possible to use breakpoints to induce it in the simulator.

ddyer0 commented 4 years ago

One more note about this; at the point where the offending component is being added, a splash screen is being presented and removed in a separate thread - so tweaks to that other process are likely to perturb this error.

ddyer0 commented 4 years ago

Not enough to be definitive yet, but I changed the frame.dispose() in the example splash screen to frame.remove() and that seems to have fixed the problem. This isn't the first time I've run into trouble with .dispose() - maybe you should just neuter it.

ddyer0 commented 4 years ago

Here's another data point, which occurred in a version which does not use "dispose()", at a later point in the process when the initial "login" screen is being swapped for the "real" top level window. The salient difference is that a dialog/form has already been presented and interacted with.

[2020/02/19 06:59:45] log request from lib.XFrame (216.165.229.150) data=[Java cpu=77% screen=1920x970 ppi=96 Codename1 3.78 0 The Android Project http://www.android.com/ 50.0 Linux i686 3.18.0-19838-gc647e70c954a] (launcher 27 threads)adding component PasswordCollector[x=0 y=0 width=0 height=0 name=null, layout = FlowLayout, scrollableX = false, scrollableY = false, components = [JPanel]] error is : java.lang.IllegalStateException: This method should not be invoked by external code! [launcher] 0:0:0,0 - Exception: java.lang.IllegalStateException - This method should not be invoked by external code! java.lang.IllegalStateException: This method should not be invoked by external code! at com.codename1.ui.util.EventDispatcher$CallbackClass.run(EventDispatcher.java:85) at com.codename1.ui.Display.callSerially(Display.java:847) at com.codename1.ui.util.EventDispatcher.fireSelectionEvent(EventDispatcher.java:409) at com.codename1.ui.list.DefaultListModel.setSelectedIndex(DefaultListModel.java:198) at com.codename1.ui.List.initComponentImpl(List.java:330) at com.codename1.ui.Container.initComponentImpl(Container.java:1136) at com.codename1.ui.Container.initComponentImpl(Container.java:1136) at com.codename1.ui.Container.initComponentImpl(Container.java:1136) at com.codename1.ui.Container.insertComponentAtImpl(Container.java:857) at com.codename1.ui.Container.insertComponentAt(Container.java:821) at com.codename1.ui.Container.addComponent(Container.java:743) at com.codename1.ui.Container.add(Container.java:362) at bridge.Container.supadd(Unknown Source:0) at bridge.Container.access$000(Unknown Source:0) at bridge.Container$1.run(Unknown Source:4) at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:95) at com.codename1.ui.Display.callSerially(Display.java:847) at com.codename1.ui.Display.callSeriallyAndWait(Display.java:936) at bridge.Platform.runInEdt(Unknown Source:14) at bridge.Container.add(Unknown Source:5) at bridge.Frame.setContentPane(Unknown Source:5) at util.PasswordCollector.createAndShowGUI(Unknown Source:107) at util.Login.initFromWebStart(Unknown Source:22) at util.JWSApplication.runLogin(Unknown Source:17) at util.JWSApplication.runMain(Unknown Source:149) at util.JWSApplication.runLobby(Unknown Source:5) at com.boardspace.BoardspaceLauncher.launchLobby(Unknown Source:123) at com.boardspace.BoardspaceLauncher.doit(Unknown Source:31) at com.boardspace.BoardspaceLauncher.run(Unknown Source:0) at java.lang.Thread.run(Thread.java:764)

ddyer0 commented 3 years ago

Here's another entry for your menagerie of "rare" crashes in the guts of your window implementation. Note that from the timestamps, these are two separate events. 23:32:14 :200 0 guest#3 73.40.70.168 0 N 3 [2020/11/17 15:00:32] log request from bridge.MasterForm (51.36.61.94) data=[Java cpu=24% screen=1080x2131 ppi=300 deviceDPI=420 scale =1.875 Codename1 4.82 0 The Android Project http://www.android.com/ 50.0 Linux aarch64 4.4.194-perf+] (EDT 17 threads)last chance error catcher error is : java.lang.NullPointerException: Attempt to invoke virtual method 'int com.codename1.ui.Form.getTintColor()' on a null object reference java.lang.NullPointerException: Attempt to invoke virtual method 'int com.codename1.ui.Form.getTintColor()' on a null object reference at com.codename1.ui.ComboBox.fireClicked(ComboBox.java:419) at com.codename1.ui.ComboBox.pointerReleased(ComboBox.java:498) at com.codename1.ui.LeadUtil.pointerReleased(LeadUtil.java:153) at com.codename1.ui.Form.pointerReleased(Form.java:3873) at com.codename1.ui.Component.pointerReleased(Component.java:4709) at bridge.MasterForm.pointerReleased(Unknown Source:28) at com.codename1.ui.Display.handleEvent(Display.java:2359) at com.codename1.ui.Display.edtLoopImpl(Display.java:1244) at com.codename1.ui.Display.mainEDTLoop(Display.java:1162) at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:120) at com.codename1.impl.CodenameOneThread$1.run(CodenameOneThread.java:60) at java.lang.Thread.run(Thread.java:919) [2020/11/17 15:45:31] log request from bridge.MasterForm (176.249.161.27) data=[Java cpu=10% screen=1242x2688 ppi=208 deviceDPI=208 scale =2.166667 Codename1 4.82 Ios] (EDT 12 threads)last chance error catcher error is : java.lang.IndexOutOfBoundsException: 0 out of: 0 java.lang.IndexOutOfBoundsException at java_util_ArrayList.get:328 at com_codename1_ui_list_DefaultListModel.getItemAt:109 at com_codename1_ui_List.setShouldCalcPreferredSize:596 at com_codename1_ui_List.dataChanged:610 at com_codename1_ui_List_Listeners.dataChanged:771 at com_codename1_ui_util_EventDispatcher.fireDataChangeSync:301 at com_codename1_ui_util_EventDispatcher.access$300:45 at com_codename1_ui_util_EventDispatcher_CallbackClass.run:105 at com_codename1_ui_Display.processSerialCalls:1338 at com_codename1_ui_Display.edtLoopImpl:1280 at com_codename1_ui_Display.mainEDTLoop:1162 at com_codename1_ui_RunnableWrapper.run:120 at com_codename1_impl_CodenameOneThread.run:176 at java_lang_Thread.runImpl:153

done

ddyer0 commented 3 years ago

[2020/12/06 19:09:49] log request from bridge.MasterForm (177.159.76.65) data=[Java cpu=44% screen=720x1399 ppi=300 deviceDPI=360 scale =1.875 Codename1 4.83 0 The Android Project http://www.android.com/ 50.0 Linux aarch64 4.4.177-19485791] (EDT 15 threads)last chance error catcher error is : java.lang.NullPointerException: Attempt to invoke virtual method 'int com.codename1.ui.Form.getTintColor()' on a null object reference java.lang.NullPointerException: Attempt to invoke virtual method 'int com.codename1.ui.Form.getTintColor()' on a null object reference at com.codename1.ui.ComboBox.fireClicked(ComboBox.java:419) at com.codename1.ui.ComboBox.pointerReleased(ComboBox.java:498) at com.codename1.ui.LeadUtil.pointerReleased(LeadUtil.java:153) at com.codename1.ui.Form.pointerReleased(Form.java:3873) at com.codename1.ui.Component.pointerReleased(Component.java:4709) at bridge.MasterForm.pointerReleased(Unknown Source:28) at com.codename1.ui.Display.handleEvent(Display.java:2359) at com.codename1.ui.Display.edtLoopImpl(Display.java:1244) at com.codename1.ui.Display.mainEDTLoop(Display.java:1162) at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:120) at com.codename1.impl.CodenameOneThread$1.run(CodenameOneThread.java:60) at java.lang.Thread.run(Thread.java:919)

ddyer0 commented 1 year ago

And another [2022/11/29 09:58:39] log request from bridge.MasterForm (213.73.150.21) data=[Java cpu=16% screen=828x1792 ppi=200 deviceDPI=200 scale =2.083333 Codename1 6.82 os.name=Ios] (EDT 15 threads)last chance error catcher error is : java.lang.IndexOutOfBoundsException: 0 out of: 0 java.lang.IndexOutOfBoundsException at java_util_ArrayList.get:328 at com_codename1_ui_list_DefaultListModel.getItemAt:109 at com_codename1_ui_List.setShouldCalcPreferredSize:596 at com_codename1_ui_List.dataChanged:610 at com_codename1_ui_List_Listeners.dataChanged:771 at com_codename1_ui_util_EventDispatcher.fireDataChangeSync:301 at com_codename1_ui_util_EventDispatcher.access$300:45 at com_codename1_ui_util_EventDispatcher_CallbackClass.run:105 at com_codename1_ui_Display.executeSerialCall:1395 at com_codename1_ui_Display.processSerialCalls:1379 at com_codename1_ui_Display.edtLoopImpl:1321 at com_codename1_ui_Display.mainEDTLoop:1203 at com_codename1_ui_RunnableWrapper.run:120 at com_codename1_impl_CodenameOneThread.run:176 at java_lang_Thread.runImpl:153 [history:

ddyer0 commented 1 year ago

Possibly also related [2023/07/16 15:31:13] log request from bridge.MasterForm (174.172.219.127) data=[Java cpu=12% screen=1125x2436 ppi=200 deviceDPI=200 scale =2.083333 platform =Ios 7.45 Codename1 os.name=Ios] (EDT 8 threads)last chance error catcher error is : java.lang.NullPointerException java.lang.NullPointerException at com_codename1_impl_ios_IOSImplementation.getDisplaySafeArea:257 at com_codename1_ui_Form.getSafeArea:560 at bridge_MasterForm.adjustSpacer:1709 at bridge_MasterForm.layoutContainer:5149 at com_codename1_ui_Container.paint:2101 at com_codename1_ui_Form.paint:4549 at bridge_MasterForm.paint:4574 at com_codename1_ui_Component.internalPaintImpl:2795 at com_codename1_ui_Form.internalPaintImpl:4559 at com_codename1_ui_Component.paintInternalImpl:2768 at com_codename1_ui_Component.paintInternal:2743 at com_codename1_ui_Component.paintInternal:2705 at com_codename1_ui_Component.paintComponent:3015 at com_codename1_ui_Component.paintComponent:2959 at com_codename1_impl_CodenameOneImplementation.paintDirty:625 at com_codename1_ui_Display.edtLoopImpl:1300 at com_codename1_ui_Display.mainEDTLoop:1203 at com_codename1_ui_RunnableWrapper.run:120 at com_codename1_impl_CodenameOneThread.run:176 at java_lang_Thread.runImpl:153 [history: