I have commented out that call, have to rebuild head slf4j with skipTests=true but it builds and now the app runs correctly. Tested again with unmodified slf4h head, bug reproduced.
The root problem is that GAE has a whitelist of J2SE APIs, but the whitelist checking is not very simple. You can see in the top of the stack trace that GAE's RuntimeHelper intercepts the call StaticLoggerBinder -> LogManager, as part of application code that invokes the allowed slf4j's getLogger(). getLogManager(), I see it's invoked by GAE's own initialization:
Thread [main] (Suspended (breakpoint at line 299 in LogManager)) LogManager.getLogManager() line: 299 [local variables unavailable] LogManager$RootLogger(Logger).<init>(String, String, Class<?>, boolean) line: 265 LogManager$RootLogger.<init>(LogManager) line: 1468 LogManager$RootLogger.<init>(LogManager, LogManager$1) line: 1466 LogManager$1.run() line: 204 AccessController.doPrivileged(PrivilegedAction<T>) line: not available [native method] LogManager.<clinit>() line: 181 Logger.demandLogger(String, String, Class<?>) line: 339 Logger.getLogger(String) line: 393 AppEngineDevAgent.<clinit>() line: 33 NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57 DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43 Method.invoke(Object, Object...) line: 606 InstrumentationImpl.loadClassAndStartAgent(String, String, String) line: 382 InstrumentationImpl.loadClassAndCallPremain(String, String) line: 397
...and then everything works, even calls coming from unprivilege app code, because once the LogManager class has been classloaded, all subsequent calls are NOT checked by the whitelist checker! which relies on classloading for that. Unlike J2EE servers, GAE is a single-app runtime and it does not use separate classloaders to isolate application modules and libraries etc. so when some class is loaded, it's loaded.
Now if you look at https://cloud.google.com/appengine/docs/java/jrewhitelist, the java.util.logging API is supported, except that LogManager is not supported, because GAE wants to have control of JUL initialization. But the best it can do it making sure the GAE runtime is the first code to call LogManager. Even if app code is fully class-initialized before GAE configures its logging, that app could easily subvert the whitelist by calling LogManager from any code that's not executed at class-init or context-init time, but maybe that's less of a problem.
|