[slf4j-user] SLF4J on the Google Android Platform

Thorsten Möller Thorsten.Moeller at unibas.ch
Wed Mar 10 17:13:28 CET 2010


Hi Chiao,

now the promised reply ...


On Wednesday, March 03, 2010 11:34 AM [GMT+1=CET],
Chiao Cheng <zimazenini at yahoo.com> wrote (with possible deletions):

> Hi All,
>
> I was playing around with android and was glad to see that someone
> already put together a slf4j-android module.  I tried using it and I
> really like to make some changes so I created another fork.
>
> First, I found an old thread explaining why slf4j-android also
> includes slf4j-api code...
>
>> I can already tell you that I needed to merge the SLf4J-API project
>> and
>> the new binding implementation into one (Maven) project. The reason
>> is
>> rather complicated to explain. In short, it is due to the fact that
>> SLF4J API removes the dummy impl.* classes during the build from the
>> target Jar, which is not compatible with the Android Dexer
> I'm not
> sure why this would be the case because the dexer is completely ok
> with dex'ing multiple jars and dependencies.

The reason is the following (explained not using real class names for 
brevity): The SLF4J API project contains some "dummy" classes, say C_1 
... C_n, which will be compiled during the build but not included in the 
final binary jar. Furterhmore, other classes in the API project, say D_1 
... D_m *depend on* one or more of C_1 ... C_n, that is, they import at 
least one of them. Now, each SLF4J binding implementation provides 
"real" implementations of C_1 ... C_n. At runtime, a Java classloader 
then loads the real implementations C_1 ... C_n when one of D_1 ... D_m 
is loaded. This works for "standard" Java SDKs. However, on the Android 
platform, final application archives are created by the Dexer (which 
does several things which are not relevant here). When the Dexer runs at 
build time and processes the compiled classes D_1 ... D_m it is somehow 
(for reasons I don't know) fixated to the original dummy implementations 
of C_1 ... C_n and not the real implementations provided by the binding 
implementation. Since the original ones were deleted it cannot find them 
(even though the real implementations do exist), throws an error 
message, and stops, rendering the build to fail.


>  I suggest we separate
> out slf4j-api code from the slf4j-android module.  Once we do this,
> then it would be easier to keep the two in sync.  With the current
> setup, it seems like it would be very easy for slf4j-android to fall
> out of sync with the main api version.
That's is actually true. The merging of both needed to be done in order 
to fix the abovementioned problem. I know that it is not optimal. My 
original idea was to make symbolic links to the SLF4J API classes. This 
would have prevented them to fall apart. Setting such links is possible 
in SVN, at least. However, since I couldn't find any information whether 
Git also supports symbolic links, I finally decided to accept this 
weakness in order to keep the whole thing simple.


> And from the web page, it
> seems like it has already fallen behind.
Yes, meanwhile there is SLF4J 1.5.11.

> Next, I found a problem in the recent access modifier changes in
> slf4j.  Specifically the references from LoggerFactory to private
> StaticLoggerBinder.SINGLETON.  Even though the java runtime seems to
> be ok due to shortcircuit logic I'm guessing, the android runtime is
> not:
>
> "access denied from Lorg/slf4j/LoggerFactory; to field
> Lorg/slf4j/impl/StaticLoggerBinder;.SINGLETON"
>
> For now, I had to change StaticLoggerBinder.SINGLETON back to public
> to avoid these errors.  But, from looking at the code, I do not see
> any reasons for LoggerFactory to reference
> StaticLoggerBinder.SINGLETON, other than allowing some modules to
> work without a getSingleton() method.
>  But I would love to remove
> SINGLETON references in the LoggerFactory.  Also seems a bit hacky to
> have code that tries to access private members.  Are there plans to
> get rid of the SINGLETON references completely?
I cannot comment on that since I'm not involved in the API development.


>
> Finally the only other change I made was to remove the systempath in
> the pom.xml.  Users can simply install a 3rd party jar in their local
> repository with the provided maven command so there is really no need
> to have that.  And to make things simpler, there is already an
> android-maven-plugin which will install the jars for you in your
> local-repository
> (http://code.google.com/p/maven-android-plugin/wiki/GettingStarted).
Where is this described. I cannot find that.

Anyway, the solution I created (using the system path) is considered a 
temporary one. Actually, it should work in most cases right away since 
the ANDROID_HOME variable will be set together with installing the SDK. 
And I'm not happy with replicating the Android jars in the local Maven 
repository since everybody would have them on disk anyway. I think a 
clean solution is to use the toolchains plugin 
(http://maven.apache.org/guides/mini/guide-using-toolchains.html) once 
it is generally available and supported by the android-maven plugin.

Cheers,
Thorsten 




More information about the slf4j-user mailing list