Compare commits

..

8 Commits

Author SHA1 Message Date
niccolo.piazzesi
21d73170e5 Upgrade proguardCORE, address API changes 2026-02-03 11:30:53 +01:00
niccolo.piazzesi
164e3d8f4d Remove java-test-fixtures plugin
The Java-test-fixtures plugin would create incorrect pom files. Since we  don't actually define test fixtures in Proguard (the published jars are empty, you can look older releases), we can just remove it.
2026-01-21 12:03:07 +01:00
niccolo.piazzesi
6776d6a3aa Prepare for 7.8.2 release
Summary: Update all relevant docs to prepare for release containing D56358

Reviewers: dominik.huber, thomas.vochten

Reviewed By: dominik.huber, thomas.vochten

Differential Revision: https://phabricator.guardsquare.com/D57357
2025-12-03 12:32:49 +01:00
niccolo.piazzesi
e1e2689c72 Document support up until java 25 2025-12-01 09:50:36 +01:00
piazzesiNiccolo-GS
14dcc28ba2 Reapply moved InterfaceUsageMarker to fx interface constant marking (#510) 2025-12-01 09:47:13 +01:00
niccolo.piazzesi
0c51b82946 Use latest version in all documentation 2025-10-27 09:11:20 +01:00
piazzesiNiccolo-GS
68dcc9880e Update proguard version 2025-10-27 09:08:23 +01:00
niccolo.piazzesi
7a76843f0c Add release note 2025-10-27 09:03:19 +01:00
20 changed files with 146 additions and 54 deletions

View File

@@ -108,7 +108,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.guardsquare:proguard-gradle:7.8.0'
classpath 'com.guardsquare:proguard-gradle:7.8.2'
}
}
```

View File

@@ -1,6 +1,5 @@
plugins {
id 'java-library'
id 'java-test-fixtures'
id 'maven-publish'
id "org.jetbrains.kotlin.jvm"
id 'com.adarshr.test-logger' version '4.0.0'

View File

@@ -131,16 +131,19 @@ implements KotlinMetadataVisitor,
kotlinPropertyMetadata.flags.hasAnnotations = false;
}
if (kotlinPropertyMetadata.referencedGetterMethod != null)
if (kotlinPropertyMetadata.getterMetadata != null &&
kotlinPropertyMetadata.getterMetadata.referencedMethod != null)
{
kotlinPropertyMetadata.referencedGetterMethod.accept(clazz, annotationCounter.reset());
kotlinPropertyMetadata.getterFlags.hasAnnotations = annotationCounter.getCount() > 0;
kotlinPropertyMetadata.getterMetadata.referencedMethod.accept(clazz, annotationCounter.reset());
kotlinPropertyMetadata.getterMetadata.hasAnnotations = annotationCounter.getCount() > 0;
}
if (kotlinPropertyMetadata.flags.isVar && kotlinPropertyMetadata.referencedSetterMethod != null)
if (kotlinPropertyMetadata.flags.isVar &&
kotlinPropertyMetadata.setterMetadata != null &&
kotlinPropertyMetadata.setterMetadata.referencedMethod != null)
{
kotlinPropertyMetadata.referencedSetterMethod.accept(clazz, annotationCounter.reset());
kotlinPropertyMetadata.setterFlags.hasAnnotations = annotationCounter.getCount() > 0;
kotlinPropertyMetadata.setterMetadata.referencedMethod.accept(clazz, annotationCounter.reset());
kotlinPropertyMetadata.setterMetadata.hasAnnotations = annotationCounter.getCount() > 0;
}
}
@@ -278,9 +281,10 @@ implements KotlinMetadataVisitor,
kotlinPropertyMetadata,
this);
if (kotlinValueParameterMetadata.flags.hasAnnotations)
if (kotlinValueParameterMetadata.flags.hasAnnotations &&
kotlinPropertyMetadata.setterMetadata != null)
{
kotlinPropertyMetadata.referencedSetterMethod.accept(clazz, annotationCounter.reset());
kotlinPropertyMetadata.setterMetadata.referencedMethod.accept(clazz, annotationCounter.reset());
kotlinValueParameterMetadata.flags.hasAnnotations =
annotationCounter.getParameterAnnotationCount(kotlinValueParameterMetadata.index) > 0;
}

View File

@@ -146,8 +146,8 @@ public class Marker implements Pass
KotlinDeclarationContainerMetadata kotlinDeclarationContainerMetadata,
KotlinPropertyMetadata kotlinPropertyMetadata) {
List<Processable> processables = Stream.of(kotlinPropertyMetadata.referencedBackingField,
kotlinPropertyMetadata.referencedGetterMethod,
kotlinPropertyMetadata.referencedSetterMethod)
kotlinPropertyMetadata.getterMetadata.referencedMethod,
kotlinPropertyMetadata.setterMetadata != null ? kotlinPropertyMetadata.setterMetadata.referencedMethod : null)
.filter(Objects::nonNull)
.collect(Collectors.toList());
int flags = 0;

View File

@@ -64,11 +64,13 @@ implements KotlinMetadataVisitor,
if ((kotlinPropertyMetadata.referencedBackingField != null &&
(kotlinPropertyMetadata.referencedBackingField.getProcessingFlags() & ProcessingFlags.DONT_OBFUSCATE) != 0) ||
(kotlinPropertyMetadata.referencedGetterMethod != null &&
(kotlinPropertyMetadata.referencedGetterMethod.getProcessingFlags() & ProcessingFlags.DONT_OBFUSCATE) != 0) ||
(kotlinPropertyMetadata.getterMetadata != null &&
kotlinPropertyMetadata.getterMetadata.referencedMethod != null &&
(kotlinPropertyMetadata.getterMetadata.referencedMethod.getProcessingFlags() & ProcessingFlags.DONT_OBFUSCATE) != 0) ||
(kotlinPropertyMetadata.referencedSetterMethod != null &&
(kotlinPropertyMetadata.referencedSetterMethod.getProcessingFlags() & ProcessingFlags.DONT_OBFUSCATE) != 0))
(kotlinPropertyMetadata.setterMetadata != null &&
kotlinPropertyMetadata.setterMetadata.referencedMethod != null &&
(kotlinPropertyMetadata.setterMetadata.referencedMethod.getProcessingFlags() & ProcessingFlags.DONT_OBFUSCATE) != 0))
{
return;
}

View File

@@ -114,14 +114,14 @@ implements KotlinMetadataVisitor,
KotlinPropertyMetadata kotlinPropertyMetadata)
{
keepParameterInfo = false;
if (kotlinPropertyMetadata.referencedSetterMethod != null)
if (kotlinPropertyMetadata.setterMetadata != null && kotlinPropertyMetadata.setterMetadata.referencedMethod != null)
{
kotlinPropertyMetadata.referencedSetterMethod.accept(clazz, this);
kotlinPropertyMetadata.setterMetadata.referencedMethod.accept(clazz, this);
}
if (keepParameterInfo)
{
kotlinPropertyMetadata.setterParametersAccept(clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.setterParameterAccept(clazz, kotlinDeclarationContainerMetadata, this);
}
}

View File

@@ -108,8 +108,8 @@ public class KotlinContextReceiverUsageMarker implements
public void visitAnyProperty(Clazz clazz, KotlinDeclarationContainerMetadata kotlinDeclarationContainerMetadata, KotlinPropertyMetadata kotlinPropertyMetadata)
{
markContextReceiverParameters(kotlinPropertyMetadata.contextReceivers,
kotlinPropertyMetadata.referencedGetterMethod,
kotlinPropertyMetadata.referencedSetterMethod);
kotlinPropertyMetadata.getterMetadata.referencedMethod,
kotlinPropertyMetadata.setterMetadata != null ? kotlinPropertyMetadata.setterMetadata.referencedMethod : null);
}
private void markContextReceiverParameters(List<KotlinTypeMetadata> contextReceivers, Method...methods)

View File

@@ -1869,11 +1869,13 @@ implements ClassVisitor,
kotlinPropertyMetadata.referencedBackingField != null &&
isUsed(kotlinPropertyMetadata.referencedBackingField);
boolean getterUsed =
kotlinPropertyMetadata.referencedGetterMethod != null &&
isUsed(kotlinPropertyMetadata.referencedGetterMethod);
kotlinPropertyMetadata.getterMetadata != null &&
kotlinPropertyMetadata.getterMetadata.referencedMethod != null &&
isUsed(kotlinPropertyMetadata.getterMetadata.referencedMethod);
boolean setterUsed =
kotlinPropertyMetadata.referencedSetterMethod != null &&
isUsed(kotlinPropertyMetadata.referencedSetterMethod);
kotlinPropertyMetadata.setterMetadata != null &&
kotlinPropertyMetadata.setterMetadata.referencedMethod != null &&
isUsed(kotlinPropertyMetadata.setterMetadata.referencedMethod);
if (backingFieldUsed || getterUsed || setterUsed)
{
@@ -1914,7 +1916,7 @@ implements ClassVisitor,
kotlinPropertyMetadata.receiverTypeAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.contextReceiverTypesAccept(clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.typeParametersAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.setterParametersAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.setterParameterAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.typeAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.versionRequirementAccept( clazz, kotlinDeclarationContainerMetadata, this);
}

View File

@@ -26,6 +26,7 @@ import proguard.classfile.kotlin.KotlinClassKindMetadata;
import proguard.classfile.kotlin.KotlinConstants;
import proguard.classfile.kotlin.KotlinConstructorMetadata;
import proguard.classfile.kotlin.KotlinDeclarationContainerMetadata;
import proguard.classfile.kotlin.KotlinEnumEntryMetadata;
import proguard.classfile.kotlin.KotlinFileFacadeKindMetadata;
import proguard.classfile.kotlin.KotlinFunctionMetadata;
import proguard.classfile.kotlin.KotlinMetadata;
@@ -38,6 +39,7 @@ import proguard.classfile.kotlin.KotlinTypeMetadata;
import proguard.classfile.kotlin.KotlinTypeParameterMetadata;
import proguard.classfile.kotlin.KotlinValueParameterMetadata;
import proguard.classfile.kotlin.KotlinVersionRequirementMetadata;
import proguard.classfile.kotlin.flags.KotlinPropertyAccessorMetadata;
import proguard.classfile.kotlin.visitor.AllTypeVisitor;
import proguard.classfile.kotlin.visitor.KotlinConstructorVisitor;
import proguard.classfile.kotlin.visitor.KotlinFunctionVisitor;
@@ -110,8 +112,7 @@ implements KotlinMetadataVisitor,
shrinkMetadataArray(kotlinClassKindMetadata.constructors);
shrinkArray(kotlinClassKindMetadata.enumEntryNames,
kotlinClassKindMetadata.referencedEnumEntries);
shrinkEnumEntries(kotlinClassKindMetadata.enumEntries);
shrinkArray(kotlinClassKindMetadata.nestedClassNames,
kotlinClassKindMetadata.referencedNestedClasses);
@@ -167,7 +168,7 @@ implements KotlinMetadataVisitor,
{
kotlinPropertyMetadata.versionRequirementAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.typeAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.setterParametersAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.setterParameterAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.receiverTypeAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.contextReceiverTypesAccept(clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.typeParametersAccept( clazz, kotlinDeclarationContainerMetadata, this);
@@ -179,21 +180,18 @@ implements KotlinMetadataVisitor,
kotlinPropertyMetadata.referencedBackingField = null;
}
if (shouldShrinkMetadata(kotlinPropertyMetadata.getterSignature,
kotlinPropertyMetadata.referencedGetterMethod))
if (shouldShrinkMetadata(kotlinPropertyMetadata.getterMetadata))
{
kotlinPropertyMetadata.getterSignature = null;
kotlinPropertyMetadata.referencedGetterMethod = null;
kotlinPropertyMetadata.getterMetadata.signature = null;
kotlinPropertyMetadata.getterMetadata.referencedMethod = null;
}
if (shouldShrinkMetadata(kotlinPropertyMetadata.setterSignature,
kotlinPropertyMetadata.referencedSetterMethod))
if (shouldShrinkMetadata(kotlinPropertyMetadata.setterMetadata))
{
kotlinPropertyMetadata.setterSignature = null;
kotlinPropertyMetadata.referencedSetterMethod = null;
kotlinPropertyMetadata.flags.isVar = false;
kotlinPropertyMetadata.setterParameter = null;
kotlinPropertyMetadata.setterParameters.clear();
kotlinPropertyMetadata.setterMetadata.signature = null;
kotlinPropertyMetadata.setterMetadata.referencedMethod = null;
kotlinPropertyMetadata.flags.isVar = false;
kotlinPropertyMetadata.setterParameter = null;
}
kotlinPropertyMetadata.versionRequirementAccept(clazz,
@@ -206,7 +204,7 @@ implements KotlinMetadataVisitor,
kotlinPropertyMetadata.syntheticMethodForAnnotations = null;
kotlinPropertyMetadata.referencedSyntheticMethodForAnnotations = null;
kotlinPropertyMetadata.referencedSyntheticMethodClass = null;
kotlinPropertyMetadata.flags.hasAnnotations = false;
kotlinPropertyMetadata.annotations.clear();
}
if (kotlinPropertyMetadata.syntheticMethodForDelegate != null &&
@@ -220,8 +218,10 @@ implements KotlinMetadataVisitor,
// Fix inconsistencies that were introduced as
// a result of shrinking
if (kotlinPropertyMetadata.referencedBackingField != null &&
kotlinPropertyMetadata.getterSignature == null &&
kotlinPropertyMetadata.setterSignature == null &&
(kotlinPropertyMetadata.setterMetadata == null ||
kotlinPropertyMetadata.setterMetadata.signature == null) &&
(kotlinPropertyMetadata.getterMetadata == null ||
kotlinPropertyMetadata.getterMetadata.signature == null) &&
(kotlinPropertyMetadata.referencedBackingField.getAccessFlags() & AccessConstants.PRIVATE) != 0 &&
!kotlinPropertyMetadata.flags.visibility.isPrivate)
{
@@ -398,6 +398,10 @@ implements KotlinMetadataVisitor,
return metadataElement != null &&
!usageMarker.isUsed(jvmElement);
}
private boolean shouldShrinkMetadata(KotlinPropertyAccessorMetadata kotlinPropertyAccessorMetadata) {
return kotlinPropertyAccessorMetadata != null && !usageMarker.isUsed(kotlinPropertyAccessorMetadata.referencedMethod);
}
/**
@@ -412,10 +416,13 @@ implements KotlinMetadataVisitor,
shrinkArray(usageMarker, elements, referencedJavaElements);
}
private void shrinkEnumEntries(List<KotlinEnumEntryMetadata> enumEntries) {
enumEntries.removeIf(usageMarker::isUsed);
}
/**
* Shrinks elements and their corresponding referenced element, based on
* markings on the referenced element.
*
* List is modified - must be a modifiable list!
*/
static void shrinkArray(SimpleUsageMarker usageMarker,

View File

@@ -129,6 +129,9 @@ public class UsageMarker
new LocalVariableTypeUsageMarker(classUsageMarker)
))));
// Second Interface Usage marking, this is necessary for marking interface constants that are not directly referenced
// (e.g. interfaces only referenced through annotations). See https://github.com/Guardsquare/proguard/issues/508.
programClassPool.classesAccept(new InterfaceUsageMarker(classUsageMarker));
if (configuration.keepKotlinMetadata)
{

View File

@@ -21,6 +21,74 @@ import proguard.testutils.RequiresJavaVersion
import proguard.util.ProcessingFlagSetter
import proguard.util.ProcessingFlags.DONT_SHRINK
class UsageMarkerTest : BehaviorSpec({
Given("A class pool with interfaces only referenced through annotations") {
val (programClassPool, _) = ClassPoolBuilder.fromSource(
JavaSource("MyInterface.java","""
interface MyInterface {}
""".trimIndent()),
JavaSource("MyAnnotation.java","""
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Retention;
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
Class<?> value();
}
""".trimIndent()),
JavaSource("MyImpl.java","""
class MyImpl implements MyInterface {}
""".trimIndent()),
JavaSource("InterfaceTest.java", """
import java.lang.reflect.Field;
class InterfaceTest {
@MyAnnotation(MyImpl.class)
String s;
public static void main(String... args) throws Exception {
Field f = InterfaceTest.class.getDeclaredField("s");
MyAnnotation annotation = f.getAnnotation(MyAnnotation.class);
Object obj = annotation.value().getDeclaredConstructor().newInstance();
if (obj instanceof MyInterface) {
System.out.println("success");
} else {
throw new Exception(obj.getClass() + " does not implement " + MyInterface.class);
}
}
}
""".trimIndent())
)
val implClass = programClassPool.getClass("MyImpl")
val main = programClassPool.getClass("InterfaceTest")
main.accept(
MultiClassVisitor(ProcessingFlagSetter(DONT_SHRINK), AllMemberVisitor(
ProcessingFlagSetter(DONT_SHRINK)
)))
When("marking") {
val simpleUsageMarker = SimpleUsageMarker()
UsageMarker(Configuration()).mark(programClassPool,ClassPool(), ResourceFilePool(),simpleUsageMarker)
Then("The interface class should be marked as used.") {
val used = object : ConstantVisitor {
var used = false
override fun visitAnyConstant(
clazz: Clazz?,
constant: Constant?
) {
used = used or simpleUsageMarker.isUsed(constant)
}
}
implClass.interfaceConstantsAccept(used)
used.used shouldBe true
}
}
}
})
@RequiresJavaVersion(15)
class Java15UsageMarkerTest : BehaviorSpec({
// Regression test for https://github.com/Guardsquare/proguard/issues/501

View File

@@ -68,9 +68,9 @@ Yes, you can. **ProGuard** itself is distributed under the GPL, but this
doesn't affect the programs that you process. Your code remains yours, and its
license can remain the same.
## Does ProGuard work with Java 2, 5,..., 19? {: #jdk1.4}
## Does ProGuard work with Java 2, 5,..., 25? {: #jdk1.4}
Yes, **ProGuard** supports all JDKs from 1.1 up to and including 19. Java 2
Yes, **ProGuard** supports all JDKs from 1.1 up to and including 25. Java 2
introduced some small differences in the class file format. Java 5 added
attributes for generics and for annotations. Java 6 introduced optional
preverification attributes. Java 7 made preverification obligatory and

View File

@@ -1,4 +1,4 @@
Welcome to the manual for **ProGuard** version 7.8.0 ([what's new?](releasenotes.md)).
Welcome to the manual for **ProGuard** version 7.8.2 ([what's new?](releasenotes.md)).
ProGuard is an open-sourced Java class file shrinker, optimizer, obfuscator, and
preverifier. As a result, ProGuard processed applications and libraries are smaller and faster.

View File

@@ -3,4 +3,4 @@
!!! Warning
ProGuard no longer supports backporting, and cannot backport class files compiled with Java >11.
Provide supports Java versions up to and including 19.
Provide supports Java versions up to and including 25.

View File

@@ -1,8 +1,15 @@
## Version 7.8.2
### Bugfixes
- Fix regression in marking of interface constants (#508).
## Version 7.8.1
### Bugfixes
- Prevent `java.lang.IncompatibleClassChangeError` when shrinking is enabled and sealed interfaces are used (#501).
- Prevent `java.lang.ClassCastException` when inlining (#505).
## Version 7.8

View File

@@ -7,7 +7,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.guardsquare:proguard-gradle:7.8.0'
classpath 'com.guardsquare:proguard-gradle:7.8.2'
}
}

View File

@@ -7,7 +7,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.guardsquare:proguard-gradle:7.8.0'
classpath 'com.guardsquare:proguard-gradle:7.8.2'
}
}

View File

@@ -5,7 +5,7 @@ buildscript {
google()
}
dependencies {
classpath("com.guardsquare:proguard-gradle:7.8.0")
classpath("com.guardsquare:proguard-gradle:7.8.2")
}
}

View File

@@ -7,7 +7,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.guardsquare:proguard-gradle:7.8.0'
classpath 'com.guardsquare:proguard-gradle:7.8.2'
}
}

View File

@@ -1,7 +1,7 @@
proguardVersion = 7.8.1
proguardVersion = 7.9.0
# The version of ProGuardCORE that sub-projects are built with
proguardCoreVersion = 9.2.0
proguardCoreVersion = 9.3.0
gsonVersion = 2.11.0
kotlinVersion = 2.2.0
target = 1.8