Android Question R8 java.lang.ClassNotFoundException: xxx.dateutils$_period

Alessandro71

Well-Known Member
Licensed User
Longtime User
while porting an existing, working app to R8, compile works fine but at runtime I have a ClassNotFoundException referring to dateutils$_period
commenting out #R8Optimizer: True turn the app back to normal behavior

i also noted that while DateUtils is listed as Internal in the Libraries Manager, it has version 1.10, while it's 1.05 in the Online column
 
I had runtime classnotfoundexception with R8, too. I add keep class in manifest to fix them.

B4X:
AddProguardText(
    -keep class xxx.dateutils.** { *; }
)

I think thats the correct name? you can try it.
 
Upvote 0
still same exception
Try this, proywill.nkt work though.

B4X:
AddProguardText(
-keep class **.dateutils$_period { *; }
)

Try using a wildcard instead...
 
Upvote 0
Solution
This is strange as there is a rule in DateUtils.proguard to keep b4a.example.dateutils._period. I'm unable to reproduce this.

Do you get this error with a new project with DateUtils selected?
I was unable to reproduce it in a new project, but the last suggestion from Peter fixed it
 
Upvote 0
This is strange as there is a rule in DateUtils.proguard to keep b4a.example.dateutils._period. I'm unable to reproduce this.

Do you get this error with a new project with DateUtils selected?
1. The Typo/Format Discrepancy (._period vs $_period)
Notice the syntax difference:
What you typed / what was tried: b4a.example.dateutils._period (using a dot .)
What Java actually uses for inner types: b4a.example.dateutils$_period (using a dollar sign $)
In compiled Java bytecode, an inner class or custom structure inside a module uses a $ sign, not a dot. If a ProGuard keep rule is written with ._period, R8 won't match the inner type and will strip it out anyway.
2. The Package Name Mismatch
When a developer wrote:

B4X:
AddProguardText(-keep class b4a.example.dateutils$_period { *; })

that rule only works if the project's Package Name in Build Configurations is literally left as b4a.example.
If the developer renamed their package to something else (e.g. com.mycompany.app), then the compiled Java class becomes com.mycompany.app.dateutils$_period. Hardcoding b4a.example in the rule means R8 ignores it and the crash still happens.
3. Another Forum Member Suggested xxx
Another forum user posted AddProguardText(-keep class xxx.dateutils.** { *; }) assuming xxx would act like a wildcard, but ProGuard treated xxx as a literal package named "xxx". That's why the original poster kept reporting: "still same exception".
The Clean Solution That Ended Up Working
Peter Simpson resolved the thread by providing the universal wildcard rule:

B4X:
AddProguardText(-keep class **.dateutils$_period { *; })

Why this works for everyone:
The ** wildcard: Matches any package name (b4a.example, com.company.app, etc.).
The $_period symbol: Uses the correct Java dollar-sign syntax ($) for inner custom types rather than a dot (.).

Example.

If your package name in B4A is my.project, then the compiled Java class path becomes:
  • my.project.dateutils (for the DateUtils code module)
  • my.project.dateutils$_period (for the Period structure inside it)
 
Last edited:
Upvote 0
Another explaination.

1. Code Modules (.bas files) \rightarrow Use YOUR Package Name
When you add raw B4A code modules (like DateUtils.bas, XUI Views.bas, or custom .bas modules) directly to your project:
The B4A compiler generates the Java code dynamically during the build process.
It places those generated Java classes inside your project's current package path (e.g., com.issac.app.dateutils$_period).
Result: If you change your project's Package Name in Build Configurations, this class's Java path changes along with it.
2. Compiled Libraries (.jar / .xml / .aar) \rightarrow Keep THEIR Original Package Name
When you check a compiled external library in the B4A Libraries tab (like JavaObject, Encryption, OkHttpUtils2, Google Play Services, or custom Java/B4X libraries built as .jar):
The code inside those .jar files was pre-compiled before you opened your project.
Their Java classes keep their fixed, original package names regardless of what you set in Build Configurations.
Example: anywheresoftware.b4a.objects.XUI or com.google.android.gms.ads.**
Result: Changing your project's package name to com.issac.app does not touch those library package paths.

You have pointed out a key rule of thumb in B4A optimization:
For external .jar libraries, you can target their exact, static package name in ProGuard rules.
For B4A .bas code modules, because their compiled Java package depends on your project's Build Configuration, you should always use the ** wildcard so renaming your project won't break your build!
 
Last edited:
Upvote 0
Back
Top