<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/feeds.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://chameth.com/">
    <title>Chameth.com - posts like g15-ram-upgrade, obfuscating-kotlin-proguard but not docker-automatic-nginx-proxy, migrating-from-github-to-forgejo, why-you-should-be-using-https</title>
    <subtitle>Personal homepage of Chris Smith</subtitle>
    <link href="https://chameth.com/feeds/posts/like/g15-ram-upgrade,obfuscating-kotlin-proguard/unlike/docker-automatic-nginx-proxy,migrating-from-github-to-forgejo,why-you-should-be-using-https/" rel="self"/>
    <link href="https://chameth.com/"/>
    <icon>https://chameth.com/favicon.png</icon>
    <updated>2023-07-29T00:00:00Z</updated>
    <id>https://chameth.com/</id>
    <author>
        <name>Chris Smith</name>
    </author>
    <entry>
        <title>Upgrading the RAM in a Dell G15 laptop</title>
        <link href="https://chameth.com/g15-ram-upgrade/"/>
        <updated>2023-07-29T00:00:00Z</updated>
        <id>https://chameth.com/g15-ram-upgrade/</id>
        <content xml:lang="en" type="html">&lt;figure class=&#34;image left&#34;&gt;
  &lt;picture&gt;
      &lt;source srcset=&#34;https://chameth.com/g15-ram-upgrade/g15.avif&#34; type=&#34;image/avif&#34;/&gt;
      &lt;source srcset=&#34;https://chameth.com/g15-ram-upgrade/g15.webp&#34; type=&#34;image/webp&#34;/&gt;
      &lt;img src=&#34;https://chameth.com/g15-ram-upgrade/g15.png&#34; alt=&#34;An open Dell G15 laptop&#34; loading=&#34;lazy&#34; width=&#34;580&#34; height=&#34;402&#34;/&gt;
  &lt;/picture&gt;
  &lt;figcaption&gt;&lt;p&gt;The Dell G15&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I currently use a Dell G15 laptop for work. It has served me well for a little
over a year, but recently it has been struggling a little with my day-to-day
workload. It came with 32GB of RAM — the highest possible specification at the
time&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:1&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; — but that is apparently no longer enough for me.&lt;/p&gt;
&lt;p&gt;For a recent project, I was working on a Rust library used in an Android app.
That meant running the usual glut of Android tools (Android Studio, an emulator
and at least one Gradle daemon) alongside a normal IDE (IntelliJ IDEA). Throw
in a web browser and a couple of electron apps, and I often managed to
use all 32GB.&lt;/p&gt;
&lt;p&gt;When you start swapping memory out to an encrypted disk — even an SSD — it
doesn’t make for great performance. At first, I tried to work around this
by enabling the Linux out-of-memory (OOM) killer, but it turns out that it’s not
too good with Electron apps: it will kill the large browser process, but then
the small Electron wrapper will just respawn it.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3 id=&#34;can-it-be-upgraded-or-not&#34;&gt;Can it be upgraded or not?&lt;/h3&gt;
&lt;p&gt;The obvious solution to not having enough RAM is to add more RAM. A quick look
in the manual showed this might not be possible, though. The manual includes
the following “Memory specifications” table:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Values&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Memory slots&lt;/td&gt;
&lt;td&gt;Two SODIMM slots&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory type&lt;/td&gt;
&lt;td&gt;DDR5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory speed&lt;/td&gt;
&lt;td&gt;4800&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maximum memory configuration&lt;/td&gt;
&lt;td&gt;32GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minimum memory configuration&lt;/td&gt;
&lt;td&gt;8GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory size per slot&lt;/td&gt;
&lt;td&gt;8GB or 16GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory configurations supported&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;&lt;li&gt;8 GB, 1 x 8 GB, DDR5, 4800 MHz&lt;/li&gt;&lt;li&gt;16 GB, 1 x 16 GB, DDR5, 4800 MHz&lt;/li&gt;&lt;li&gt;16 GB, 2 x 8 GB, DDR5, 4800 MHz, dual-channel&lt;/li&gt;&lt;li&gt;32 GB, 2 x 16 GB, DDR5, 4800 MHz, dual-channel&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;That unambiguously says that an upgrade from 32GB is not possible. I gave up.&lt;/p&gt;
&lt;p&gt;Later though, I was complaining about memory issues to a friend, and he pointed
out a Dell forum thread where a couple of people claim to have successfully
installed dual-channel 32GB modules. Since the alternative was getting an
entire new PC after only a year, I decided to give it a go.&lt;/p&gt;
&lt;h3 id=&#34;the-upgrade-attempt&#34;&gt;The upgrade attempt&lt;/h3&gt;
&lt;p&gt;I ordered a pair of Crucial 32GB DDR5-4800 SODIMMs, and after they turned up
dismantled the laptop. The G15 comes apart pretty normally: there are uncovered
screws on the bottom holding the lower part of the case on. With those
removed and some gentle prying, it pops off, and you get access to the battery,
GPU and motherboard.&lt;/p&gt;
&lt;p&gt;The first thing I saw was this:&lt;/p&gt;
&lt;figure class=&#34;image full&#34;&gt;
  &lt;picture&gt;
      &lt;source srcset=&#34;https://chameth.com/g15-ram-upgrade/motherboard.avif&#34; type=&#34;image/avif&#34;/&gt;
      &lt;source srcset=&#34;https://chameth.com/g15-ram-upgrade/motherboard.webp&#34; type=&#34;image/webp&#34;/&gt;
      &lt;img src=&#34;https://chameth.com/g15-ram-upgrade/motherboard.jpg&#34; alt=&#34;The G15 motherboard, with a large &amp;#34;DDR5 8G/16G Only&amp;#34; label, and a smaller &amp;#34;DIMM B DDR5 8G/16G&amp;#34; label next to a SODIMM slot&#34; loading=&#34;lazy&#34; width=&#34;1536&#34; height=&#34;1300&#34;/&gt;
  &lt;/picture&gt;
  &lt;figcaption&gt;&lt;p&gt;The G15 motherboard adamantly proclaiming that it doesn’t want 32GB SODIMMs&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Not one but two labels that indicate it will only accept 8GB or 16GB modules.
Oh well, what’s the worst that can happen?&lt;/p&gt;
&lt;h3 id=&#34;oops&#34;&gt;Oops?&lt;/h3&gt;
&lt;p&gt;I dutifully installed the new modules, reconnected the battery and put the
case back together. I pressed the power button, and… nothing. None of the
usual garish lights that immediately come on, no screen output, just a dead
laptop. After reading some more of the user manual, I found that there is a tiny
status LED on the side next to the ethernet port. Forcing the laptop to power
off and back on again, the status LED blinked a distress code at me: 2 amber
blinks, 4 white blinks. The manual says that is — unsurprisingly — a memory
fault.&lt;/p&gt;
&lt;p&gt;I figured at this point that the manual and labels on the motherboard were
probably right. I took the laptop apart again, reinstalled the original 2x16GB
modules, reassembled it, and pressed the power button. It didn’t boot. I don’t
spend a lot of time fiddling inside computers, but I’ve done it enough that
I’m reasonably confident I can’t entirely break a computer while swapping some
RAM modules. I took to Googling&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:2&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;, and found an interesting article that said
Dell laptops don’t like to boot after RAM changes unless you clear the CMOS by
popping out the battery for 15 minutes.&lt;/p&gt;
&lt;p&gt;I opened the laptop up, and looked around for the CMOS battery. There wasn’t
one. Turns out they don’t exist any more. I left the main battery disconnected
for a while to see if it would help, and it didn’t.&lt;/p&gt;
&lt;h3 id=&#34;unexpected-success&#34;&gt;Unexpected success&lt;/h3&gt;
&lt;p&gt;I started to get worried: if I couldn’t fix this, I wouldn’t be able to
work until I got a new PC, and that wasn’t really in my budget at the minute.
I sat reading old forum threads and help guides&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:3&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;, none of which were actually
useful. Out of nowhere, though, the laptop booted up.&lt;/p&gt;
&lt;p&gt;Naturally, I immediately shut the laptop down again, opened it up, and switched
back to the new RAM modules. Then I turned it on again and sat waiting. After
about 15 minutes of it looking totally dead, it turned on and showed a BIOS
warning about the hardware configuration being changed. It then booted perfectly
normally, and all 64GB of RAM was visible and usable.&lt;/p&gt;
&lt;p&gt;My theory is that the forum threads were right: Dell laptops are funny about
RAM upgrades. But somehow in removing the physical CMOS battery, they’ve kept
the same “you have to wait 15 minutes” behaviour just without any indication
that’s what’s happening. Regardless, I now have enough RAM even for the
greediest of IDEs and Electron apps.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr/&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Bizarrely, the maximum spec has &lt;em&gt;decreased&lt;/em&gt; to 16GB since then. &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:1&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;In the generic sense. I use &lt;a href=&#34;https://kagi.com/&#34;&gt;Kagi&lt;/a&gt; these days. &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:2&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;On my phone because, y’know, the laptop was busted. &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:3&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
    <entry>
        <title>Obfuscating Kotlin code with ProGuard</title>
        <link href="https://chameth.com/obfuscating-kotlin-proguard/"/>
        <updated>2019-10-21T00:00:00Z</updated>
        <id>https://chameth.com/obfuscating-kotlin-proguard/</id>
        <content xml:lang="en" type="html">&lt;figure class=&#34;image left&#34;&gt;
  &lt;picture&gt;
      &lt;source srcset=&#34;https://chameth.com/obfuscating-kotlin-proguard/kotlin-proguard.avif&#34; type=&#34;image/avif&#34;/&gt;
      &lt;source srcset=&#34;https://chameth.com/obfuscating-kotlin-proguard/kotlin-proguard.webp&#34; type=&#34;image/webp&#34;/&gt;
      &lt;img src=&#34;https://chameth.com/obfuscating-kotlin-proguard/kotlin-proguard.png&#34; alt=&#34;Kotlin and Proguard logos&#34; loading=&#34;lazy&#34; width=&#34;343&#34; height=&#34;207&#34;/&gt;
  &lt;/picture&gt;
  &lt;figcaption&gt;&lt;p&gt;Kotlin + Proguard = fun&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Obfuscating code is the process of modifying source code or build output in
order to make it harder for humans to understand. It’s often employed as a
tactic to deter reverse engineering of commercial applications or libraries
when you have no choice but to ship binaries or byte code. For Android apps,
&lt;a href=&#34;https://www.guardsquare.com/en/products/proguard&#34;&gt;ProGuard&lt;/a&gt; is part of the
default toolchain and obfuscation is usually only a config switch away.&lt;/p&gt;
&lt;p&gt;I was recently working on an Android library written in Kotlin that my client
wanted obfuscated to try and protect some of their trade secrets that were
included. Not a problem, I thought: it’s just a few lines of ProGuard config
and we’re away. Four hours and lots of hair pulling later I finally got it
working…&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3 id=&#34;if-at-first-you-dont-succeed&#34;&gt;If at first you don’t succeed…&lt;/h3&gt;
&lt;p&gt;At first it seemed like ProGuard was refusing to obfuscate any class with a
&lt;code&gt;keep&lt;/code&gt; rule. With a simple test class:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;chroma-nc&#34;&gt;Test&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-k&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;chroma-py&#34;&gt;secret&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;123&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-k&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;chroma-py&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;Chris&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-k&#34;&gt;fun&lt;/span&gt; &lt;span class=&#34;chroma-nf&#34;&gt;greet&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        &lt;span class=&#34;chroma-n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;Hi &lt;/span&gt;&lt;span class=&#34;chroma-si&#34;&gt;$name&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;! Enter a number: &amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        &lt;span class=&#34;chroma-n&#34;&gt;readLine&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;?.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;guess&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-k&#34;&gt;it&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;toInt&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;())&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-k&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;fun&lt;/span&gt; &lt;span class=&#34;chroma-nf&#34;&gt;guess&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;attempt&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;Int&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        &lt;span class=&#34;chroma-k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;attempt&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;secret&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;            &lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;Correct!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        &lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;            &lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;Nope!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        &lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And a ProGuard rule of:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;-keep public class Test {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    public void greet();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I expected that the &lt;code&gt;Test&lt;/code&gt; class and the &lt;code&gt;greet&lt;/code&gt; method would remain, but both
fields and the &lt;code&gt;guess&lt;/code&gt; method would be obfuscated. When I built the project
and opened the class from Android Studio’s APK inspector I was disappointed:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;final&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;chroma-nc&#34;&gt;Test&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;constructor&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;final&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;chroma-py&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;kotlin&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;chroma-cm&#34;&gt;/* compiled code */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-k&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;final&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;chroma-py&#34;&gt;secret&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;kotlin&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;Int&lt;/span&gt; &lt;span class=&#34;chroma-cm&#34;&gt;/* compiled code */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;final&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;fun&lt;/span&gt; &lt;span class=&#34;chroma-nf&#34;&gt;greet&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;():&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;kotlin&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;Unit&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-cm&#34;&gt;/* compiled code */&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-k&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;final&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;fun&lt;/span&gt; &lt;span class=&#34;chroma-nf&#34;&gt;guess&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;attempt&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;kotlin&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;Int&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;):&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;kotlin&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;Unit&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-cm&#34;&gt;/* compiled code */&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Having your secret sauce in a field labelled “secret” isn’t exactly the level of
obfuscation I was hoping for. ProGuard has lots of knobs that you can twist to
affect what it keeps and what it renames, but all the incantations of &lt;code&gt;-keep&lt;/code&gt;,
&lt;code&gt;-keepmembernames&lt;/code&gt;, &lt;code&gt;-allowobfuscation&lt;/code&gt;, and so on, that I could come up with
either resulted in the class completely vanishing (because it wasn’t kept) or
showing up with all its symbols intact.&lt;/p&gt;
&lt;p&gt;There are lots of useful Stack Overflow posts describing how to obfuscate
a single method, or keep a single method and obfuscate the rest, but nothing
I tried seemed to make a difference. I’m not the biggest fan of ProGuard, but
I’ve used it enough before to know that it’s not usually that hard to make
it submit to your demands. Obviously something else was going on.&lt;/p&gt;
&lt;h3 id=&#34;-maybe-youre-solving-the-wrong-problem&#34;&gt;… Maybe you’re solving the wrong problem&lt;/h3&gt;
&lt;p&gt;My next thought was that perhaps Android Studio was doing something clever
like reading the ProGuard mapping file and automatically deobfuscating the
output for me. Looking at the mapping file it seems that ProGuard has
indeed decided to rename some things:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;Test -&amp;gt; Test:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    int secret -&amp;gt; a
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    java.lang.String name -&amp;gt; b
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    void greet() -&amp;gt; greet
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    void &amp;lt;init&amp;gt;() -&amp;gt; &amp;lt;init&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The obvious solution is to look at the class file in something less smart
than Android Studio. A couple of unzips later and I could do a quick test
to see if the original names were still present:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;$ strings Test.class | grep secret
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;secret
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The problem is evidently not with Android Studio, as &lt;code&gt;secret&lt;/code&gt; shouldn’t end
up in the class file at all: it should have been entirely replaced with &lt;code&gt;a&lt;/code&gt; like
the mapping file says. The output from &lt;code&gt;javap -p&lt;/code&gt; doesn’t show any hint of the
original names, however:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;$ javap -p Test
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;public final class Test {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  private final int a;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  private java.lang.String b;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  public final void greet();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  public Test();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But, given the names show up in &lt;code&gt;strings&lt;/code&gt;, they must be kicking around
somewhere. None of the various outputs from &lt;code&gt;javap&lt;/code&gt; helped until I hit
&lt;code&gt;-verbose&lt;/code&gt;. Right at the end of the class is:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;RuntimeVisibleAnnotations:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  0: #58(#84=[I#2,I#2,I#4],#69=[I#2,I#1,I#3],#81=I#2,#70=[s#40],#71=[s#55,s#39,s#43,s#85,s#39,s#72,s#42,s#91,s#47,s#90,s#39,s#73,s#39,s#74,s#67,s#83])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    kotlin.Metadata(
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      mv=[1,1,15]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      bv=[1,0,3]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      k=1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      d1=[&amp;#34;\u0000\&amp;#34;\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\u0005\n\u0002\u0010\b\n\u0000\n\u0002\u0010\u0002\n\u0002\b\u0003\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\u0006\u0010\u000b\u001a\u00020\fJ\u0010\u0010\r\u001a\u00020\f2\u0006\u0010\u000e\u001a\u00020\nH\u0002R\u001a\u0010\u0003\u001a\u00020\u0004X\u0086\u000e¢\u0006\u000e\n\u0000\u001a\u0004\b\u0005\u0010\u0006\&amp;#34;\u0004\b\u0007\u0010\bR\u000e\u0010\t\u001a\u00020\nX\u0082D¢\u0006\u0002\n\u0000¨\u0006\u000f&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      d2=[&amp;#34;LTest;&amp;#34;,&amp;#34;&amp;#34;,&amp;#34;()V&amp;#34;,&amp;#34;name&amp;#34;,&amp;#34;&amp;#34;,&amp;#34;getName&amp;#34;,&amp;#34;()Ljava/lang/String;&amp;#34;,&amp;#34;setName&amp;#34;,&amp;#34;(Ljava/lang/String;)V&amp;#34;,&amp;#34;secret&amp;#34;,&amp;#34;&amp;#34;,&amp;#34;greet&amp;#34;,&amp;#34;&amp;#34;,&amp;#34;guess&amp;#34;,&amp;#34;attempt&amp;#34;,&amp;#34;lib_release&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    )
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There’s a Kotlin &lt;em&gt;annotation&lt;/em&gt; containing all of the symbols we were trying to
obfuscate away! Kotlin apparently uses this annotation for reflection and for
keeping track of various language features that don’t have a direct mapping in
Java bytecode (such as members with &lt;code&gt;internal&lt;/code&gt; access). Sure enough, switching
back to Android Studio and making it “decompile” the Kotlin code into Java
shows the annotation:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-nd&#34;&gt;@Metadata&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;mv&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;15&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;bv&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;d1&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;\u0000\&amp;#34;\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\u0005\n\u0002\u0010\b\n\u0000\n\u0002\u0010\u0002\n\u0002\b\u0003\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\u0006\u0010\u000b\u001a\u00020\fJ\u0010\u0010\r\u001a\u00020\f2\u0006\u0010\u000e\u001a\u00020\nH\u0002R\u001a\u0010\u0003\u001a\u00020\u0004X\u0086\u000e¢\u0006\u000e\n\u0000\u001a\u0004\b\u0005\u0010\u0006\&amp;#34;\u0004\b\u0007\u0010\bR\u000e\u0010\t\u001a\u00020\nX\u0082D¢\u0006\u0002\n\u0000¨\u0006\u000f&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;d2&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;LTest;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;()V&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;getName&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;()Ljava/lang/String;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;setName&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;(Ljava/lang/String;)V&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;secret&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;greet&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;guess&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;attempt&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;lib_release&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-kd&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;chroma-nc&#34;&gt;Test&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;solving-the-right-problem&#34;&gt;Solving the right problem&lt;/h3&gt;
&lt;p&gt;Now I had an idea of what was happening I was able to find a couple of other
reports of people having the same issue. There’s an open
&lt;a href=&#34;https://sourceforge.net/p/proguard/feature-requests/182/&#34;&gt;feature request for ProGuard to support Kotlin’s metadata annotation&lt;/a&gt;
but it’s not yet supported.&lt;/p&gt;
&lt;p&gt;As this was a library with a fairly straight forward interface I reasoned I
could probably get ProGuard to strip out the metadata annotation. If I stopped
Kotlin reflection working in the process then that would actually be a small
bonus. Unfortunately other people with the same idea had reported back that
they were unsuccessful: even when not using the default ProGuard config,
somehow the annotations are kept.&lt;/p&gt;
&lt;p&gt;Adding a &lt;code&gt;-printconfiguration&lt;/code&gt; instruction to my configuration lets me see
the full configuration being passed to ProGuard, and the reason for keeping
quickly becomes obvious:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;-keepattributes *Annotation*,*Annotation*
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This appears to be added by the Android build plugin before it invokes
ProGuard, and there’s no obvious way to disable it. ProGuard doesn’t offer
a way to reverse this instruction, either, but fortunately the build plugin
seems to concatenate all of the &lt;code&gt;-keepattribute&lt;/code&gt; values together and puts our
user-supplied ones first. Adding a negative filter:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;-keepattributes !*Annotation*
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Results in the following in the printed configuration:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;-keepattributes !*Annotation*,*Annotation*,*Annotation*
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The negative filter prevents any subsequent filters from matching. Recompiling
and looking at the class file again looks a lot more sensible:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-kn&#34;&gt;import&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-nn&#34;&gt;kotlin.io.ConsoleKt&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-kd&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;chroma-nc&#34;&gt;Test&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;chroma-kd&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-kd&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;123&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;chroma-kd&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;Chris&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;chroma-kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-kd&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-nf&#34;&gt;greet&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;var1&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;Hi &amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-na&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;! Enter a number: &amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;System&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-na&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-na&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;var1&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;var10000&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;ConsoleKt&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-na&#34;&gt;readLine&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;chroma-k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;var10000&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;!=&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-kc&#34;&gt;null&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;         &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;var1&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;var10000&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;         &lt;/span&gt;&lt;span class=&#34;chroma-kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;var3&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;Integer&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-na&#34;&gt;parseInt&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;var1&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;         &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;var1&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;var3&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;123&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;?&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;Correct!&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;Nope!&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;         &lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;System&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-na&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-na&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;var1&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And that’s the story of how I spent half a day making a one line change.&lt;/p&gt;
</content>
    </entry>
</feed>
