Skip to main content

Precompile or Postcompile

Simple Story

The checks can be printed into your exercise before it is built, or the teacher can carry them in while the examination is already running.

Everything else on this page follows from that one choice, so make it first.

The two modes

Postcompile. Ares is a dependency of the project under test and is activated by the test methods themselves, through JupiterSecurityExtension or JqwikSecurityExtension. Nothing is generated: when a test runs, Ares installs the policy into the already-running Java Virtual Machine (JVM) and checks each action as it is attempted, so it can report exactly which file or which address was asked for. Every test may carry its own @Policy. This assumes tests run sequentially, because the enforcement settings are static fields in the bootstrap class loader.

Precompile. Ares runs once as an external tool, reads the policy, and copies a self-contained set of security test cases, aspects, configuration and the Ares classes it needs into the exercise. The target project then needs no Ares dependency of its own. One generated set applies to every test in the project, and changing the policy means regenerating and rebuilding.

Precompile and Postcompile are not the same thing as AspectJ and instrumentation

The two axes are independent in both directions. examples/ares-exercise-gradle runs JAVA_USING_GRADLE_ARCHUNIT_AND_ASPECTJ in Postcompile, and the Precompile generator can emit instrumentation just as well as aspects. The weaving mechanism comes from the policy's ProgrammingLanguageConfiguration, not from the mode.

How to choose

If you wantChoose
A different policy per test methodPostcompile
The exercise to build without an Ares dependencyPrecompile
Enforcement you can change without rebuilding the exercisePostcompile
Generated artefacts you can review and commit like any other codePrecompile
The path with runnable reference exercises todayPostcompile

Postcompile is the better default. Both runnable examples under examples/ are Postcompile exercises, and there is no runnable Precompile example yet.

What both modes require

Whichever mode you pick, the build has to do five things:

  1. Make the Ares library available, as a dependency in Postcompile or through the generated artefacts in Precompile.
  2. Weave the Ares security aspects into the compiled bytecode with the AspectJ compiler, if the configuration ends in _ASPECTJ.
  3. Download and attach the Ares agent JAR at test startup, if it ends in _INSTRUMENTATION.
  4. Grant the agent access to Java internals through the required JVM flags.
  5. Reject student classes declared in reserved packages, so that student code cannot impersonate code Ares trusts by name.

Step 5 is not optional and not mode-specific. Ares does not install it for you in either mode: the shipped snippets under configuration/reservedPackages/ are copied into your build by hand. Without it, a student can declare a class in a package Ares trusts and be trusted along with it.

Choosing a configuration

  1. Create a security policy and annotate tests: follow the Security Policy Manual, which explains how to write SecurityPolicy.yaml files and apply @Policy to your tests. @Policy selects the policy but activates nothing on its own, so each supervised test needs an Ares test annotation as well (@Public, @Hidden, @PublicTest or @HiddenTest). If your exercise needs no resource access at all, Further Options describes the alternative.
  2. Choose the right configuration: select one of the eight ProgrammingLanguageConfiguration values matching your build tool, architecture analysis and runtime enforcement:
ValueBuild ToolStatic AnalysisRuntime Enforcement
JAVA_USING_MAVEN_ARCHUNIT_AND_ASPECTJMavenArchUnit (rule-based)AspectJ (compile-time weaving)
JAVA_USING_MAVEN_ARCHUNIT_AND_INSTRUMENTATIONMavenArchUnit (rule-based)ByteBuddy agent (runtime)
JAVA_USING_MAVEN_WALA_AND_ASPECTJMavenT. J. Watson Libraries for Analysis (WALA) (call-graph)AspectJ (compile-time weaving)
JAVA_USING_MAVEN_WALA_AND_INSTRUMENTATIONMavenWALA (call-graph)ByteBuddy agent (runtime)
JAVA_USING_GRADLE_ARCHUNIT_AND_ASPECTJGradleArchUnit (rule-based)AspectJ (compile-time weaving)
JAVA_USING_GRADLE_ARCHUNIT_AND_INSTRUMENTATIONGradleArchUnit (rule-based)ByteBuddy agent (runtime)
JAVA_USING_GRADLE_WALA_AND_ASPECTJGradleWALA (call-graph)AspectJ (compile-time weaving)
JAVA_USING_GRADLE_WALA_AND_INSTRUMENTATIONGradleWALA (call-graph)ByteBuddy agent (runtime)

How to choose:

  • Build tool: match your project (MAVEN or GRADLE).
  • Static analysis: ARCHUNIT is simpler and faster; WALA detects transitive violations through call chains.
  • Runtime enforcement: INSTRUMENTATION (ByteBuddy agent) or ASPECTJ (compile-time weaving). Configure both mechanisms regardless of which you choose, so that switching is a policy edit rather than a build change.

Glossary

TermMeaning
Java AgentA JVM mechanism (-javaagent) that allows code to transform class bytecode at load time. Ares uses a ByteBuddy-based agent to intercept forbidden operations at runtime.
ByteBuddyA library for creating and modifying Java classes at runtime, used by Ares to implement the instrumentation agent.
InstrumentationThe runtime aspect-oriented programming (AOP) approach where class bytecode is modified at load time via the java.lang.instrument application programming interface (API). One of the two runtime enforcement mechanisms in Ares, alongside AspectJ.
AspectJA compile-time AOP framework used for runtime enforcement. Requires the AspectJ compiler plugin to weave aspects during the build, and the AspectJ runtime JAR on the bootstrap classpath. The compiler weaves the aspects from the Ares JAR only if that JAR is on the aspect path (Gradle: the aspect configuration; Maven: an <aspectLibraries> entry).
Aspect pathThe set of JARs ajc reads binary aspects from. Distinct from the compile classpath: a JAR on the classpath alone contributes no aspects.
CommandLineArgumentProviderThe Gradle interface used here to compute test JVM arguments when the task runs rather than when the build is configured, which keeps dependency resolution out of the configuration phase and the build configuration-cache compatible.
--add-opens / --add-exportsJVM flags that grant access to internal Java modules. Required by Ares to introspect intercepted Java Development Kit (JDK) objects.
withinPathThe path to compiled student bytecode, relative to the build output directory. Differs between Gradle (classes/java/main/...) and Maven (classes/...).
ProgrammingLanguageConfigurationAn enum encoding the combination of build tool, static analysis framework and runtime enforcement mechanism.
Classifier (:agent)A Maven/Gradle coordinate qualifier selecting a variant of an artefact. The :agent classifier selects the agent JAR, which carries the Premain-Class manifest entry and needs no repackaging.
Reserved packageA package prefix that student code may not declare, because Ares trusts that identity by name. Enforced by the build, see the reserved-package step.
PhobosA test-case family covering the file-system, network and timeout domains. Ares 2.1.5 generates Phobos cases but does not yet dispatch them from the in-process execution path, so a policy timeout does not bound a test today. Use @StrictTimeout for a deadline.
@StrictTimeoutThe annotation that bounds test execution. Applied to a test class or method, and unchanged from Ares 1 apart from its package.
Positive / negative controlThe paired checks of the two controls above: one permitted operation that must succeed, one forbidden operation that must be rejected. Neither alone demonstrates that enforcement works.