{"record":{"id":"88cd13e0c5b90417","repo":"didi/DoKit","slug":"default-singleton-instance-cannot-be-shutdown","errorCode":null,"errorMessage":"Default singleton instance cannot be shutdown.","messagePattern":"Default singleton instance cannot be shutdown\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"Android/dokit/src/main/java/com/didichuxing/doraemonkit/picasso/DokitPicasso.java","lineNumber":435,"sourceCode":"  /** {@code true} if debug logging is enabled. */\n  public boolean isLoggingEnabled() {\n    return loggingEnabled;\n  }\n\n  /**\n   * Creates a {@link StatsSnapshot} of the current stats for this instance.\n   * <p>\n   * <b>NOTE:</b> The snapshot may not always be completely up-to-date if requests are still in\n   * progress.\n   */\n  @SuppressWarnings(\"UnusedDeclaration\") public StatsSnapshot getSnapshot() {\n    return stats.createSnapshot();\n  }\n\n  /** Stops this instance from accepting further requests. */\n  public void shutdown() {\n    if (this == singleton) {\n      throw new UnsupportedOperationException(\"Default singleton instance cannot be shutdown.\");\n    }\n    if (shutdown) {\n      return;\n    }\n    cache.clear();\n    cleanupThread.shutdown();\n    stats.shutdown();\n    dispatcher.shutdown();\n    for (DeferredRequestCreator deferredRequestCreator : targetToDeferredRequestCreator.values()) {\n      deferredRequestCreator.cancel();\n    }\n    targetToDeferredRequestCreator.clear();\n    shutdown = true;\n  }\n\n  List<RequestHandler> getRequestHandlers() {\n    return requestHandlers;\n  }","sourceCodeStart":417,"sourceCodeEnd":453,"githubUrl":"https://github.com/didi/DoKit/blob/626827cddb2feb2f3aee87a52a064b4e5ca2bed4/Android/dokit/src/main/java/com/didichuxing/doraemonkit/picasso/DokitPicasso.java#L417-L453","documentation":"shutdown() releases the cache, dispatcher, executor and stats of a Picasso instance. The default singleton (from DokitPicasso.with(context)) is shared process-wide, so shutting it down would break every subsequent load; Picasso guards it with UnsupportedOperationException('Default singleton instance cannot be shutdown.'). Only instances you built yourself via new DokitPicasso.Builder(...).build() may be shut down.","triggerScenarios":"Calling DokitPicasso.with(context).shutdown(), typically in onDestroy/onTerminate/test teardown; holding a reference obtained from with() and treating it as owned.","commonSituations":"Robolectric/unit tests tearing down the singleton between test cases; library code that builds its own Picasso but accidentally calls shutdown on with()'s instance; memory-leak 'fixes' that try to release the cache on background.","solutions":["Remove the shutdown() call on the singleton — it lives for the process lifetime","If you need lifecycle-scoped instances, build your own: DokitPicasso p = new DokitPicasso.Builder(context).build(); ... p.shutdown();","In tests, use setSingletonInstance(null-equivalent) is not supported — instead build fresh instances per test rather than shutting the singleton down"],"exampleFix":"// before\n@Override protected void onDestroy() {\n  super.onDestroy();\n  DokitPicasso.with(this).shutdown(); // UnsupportedOperationException\n}\n\n// after\nprivate final DokitPicasso picasso = new DokitPicasso.Builder(this).build();\n@Override protected void onDestroy() {\n  super.onDestroy();\n  picasso.shutdown(); // OK: instance you own\n}","handlingStrategy":"validation","validationCode":"// Only shutdown instances you constructed:\nfinal DokitPicasso owned = new DokitPicasso.Builder(context).build();\n// ... later, when truly done:\nowned.shutdown();\n// NEVER: DokitPicasso.with(context).shutdown();","typeGuard":null,"tryCatchPattern":"if (picasso != null && picasso != DokitPicasso.with(context)) {\n  try { picasso.shutdown(); }\n  catch (UnsupportedOperationException e) { /* singleton — leave it alive */ }\n}","preventionTips":["Remember with() returns a process-wide singleton — it must never be shut down","In tests, build local instances per test instead of shutting the singleton","Tag owned instances (field/local) vs shared (with()) in code review"],"tags":["android","picasso","lifecycle","singleton"],"backgroundTag":null,"analyzedSha":"626827cddb2feb2f3aee87a52a064b4e5ca2bed4","analyzedAt":"2026-08-14T12:45:58.758Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}