GithubHelp home page GithubHelp logo

graalvm-filters's Introduction

GraalVM filter tests

A small application which contains a reflection call. The call stack is as follows:

Main -> static call -> A -> static call -> C -> reflect call -> B

There is a test called AppTest in the test sources which uses reflection to create an instance of App and calls the main method.

user-code-filter.json

Influences the class in the typeReachable clause. The nearest included class in the call stack leading to the reflection call is used.

Example: Setting the filter to this:

{
    "rules": [
        {
            "excludeClasses": "**"
        },
        {
            "includeClasses": "graal.filter.test.C"
        }
    ]
}

generates this reflection-config.json:

[
    {
        "name": "graal.filter.test.B",
        "condition": {
            "typeReachable": "graal.filter.test.C"
        },
        "methods": [
            {
                "name": "<init>",
                "parameterTypes": [
                ]
            },
            {
                "name": "someMethod",
                "parameterTypes": [
                ]
            }
        ]
    }
]

The call stack looks like this (invokeB:16, C is the reflection call to get the method on class B):

invokeB:16, C (graal.filter.test)
run:8, A (graal.filter.test)
main:5, App (graal.filter.test)

The first included class from the top of the stack is C, therefore the typeReachable clause is set to C.

Setting the filter to this:

{
    "rules": [
        {
            "excludeClasses": "**"
        },
        {
            "includeClasses": "graal.filter.test.A"
        }
    ]
}

results in this reflect-config.json:

[
    {
        "name": "graal.filter.test.B",
        "condition": {
            "typeReachable": "graal.filter.test.A"
        },
        "methods": [
            {
                "name": "<init>",
                "parameterTypes": [
                ]
            },
            {
                "name": "someMethod",
                "parameterTypes": [
                ]
            }
        ]
    }
]

because the call stack looks like this:

invokeB:16, C (graal.filter.test)
run:8, A (graal.filter.test)
main:5, App (graal.filter.test)

The typeReachable clause now points to A, because it is the first included class from the top of the stack.

Including both A and C with a config like this:

{
    "rules": [
        {
            "excludeClasses": "**"
        },
        {
            "includeClasses": "graal.filter.test.**"
        }
    ]
}

results in this reflect-config.json:

[
    {
        "name": "graal.filter.test.B",
        "condition": {
            "typeReachable": "graal.filter.test.C"
        },
        "methods": [
            {
                "name": "<init>",
                "parameterTypes": [
                ]
            },
            {
                "name": "someMethod",
                "parameterTypes": [
                ]
            }
        ]
    }
]

as C is the nearest included class in the call stack when the reflection is recorded.

If neither A nor C nor App is in the includeClasses, no reflection call is recorded.

Recommendation: Exclude all classes, and only include classes from your production packages:

{
    "rules": [
        {
            "excludeClasses": "**"
        },
        {
            "includeClasses": "graal.filter.test.**"
        }
    ]
}

If the tests do reflection which would be recorded by the agent, read on.

If the tests are in a separate package from the production code, exclude the whole test package:

{
    "rules": [
        {
            "excludeClasses": "**"
        },
        {
            "includeClasses": "your.production.package.**"
        },
        {
            "excludeClasses": "your.test.package.**"
        }
    ]
}

If the tests are in the same package as your production code, you can use regexRules to exclude them:

{
    "rules": [
        {
            "excludeClasses": "**"
        },
        {
            "includeClasses": "your.package.**"
        }
    ],
    "regexRules": [
        {
            "excludeClasses": "\\Qyour.package.\\E.*Test"
        }
    ]
}

This will exclude all test classes in your.package (and subpackages) ending in Test. The reflection calls by your production code will still be recorded.

caller-filter.json

Checks if the direct class which does the reflection call is included or excluded. If it's excluded, the reflection call is not recorded. Important: It has to be the direct class which does the call, not one which is in the call stack.

Example:

this caller-filter.json:

{
    "rules": [
        {
            "excludeClasses": "**"
        },
        {
            "includeClasses": "graal.filter.test.C"
        }
    ]
}

records the usage of the reflection call to B, because C is the one which does it.

This caller-filter.json:

{
    "rules": [
        {
            "excludeClasses": "**"
        },
        {
            "includeClasses": "graal.filter.test.A"
        }
    ]
}

does not record the call, as A calls C which does the reflection. A may be in the call stack, but that doesn't matter. The includeClasses only takes the direct caller into account.

That means if your code is using some library which does the reflection calls, they would not be included without additional configuration.

You could use that file to find all reflection calls which originates from your code, excluding all 3rd party calls.

access-filter.json

Checks if the target of the reflection is included. In contrast to caller-filter.json this filter acts on the target of the reflection.

This access-filter.json:

{
    "rules": [
        {
            "excludeClasses": "**"
        },
        {
            "includeClasses": "graal.filter.test.B"
        }
    ]
}

will only record reflection calls which have B as a target. You could use that file to find all reflection calls to types inside your code, excluding calls to 3rd party types.

Running it yourself

Run

./gradlew -Pagent clean test

and check the generated files under app/build/native/agent-output/test.

You can copy the collected metadata to src/main/resources with:

./gradlew metadataCopy

and then a:

./gradlew nativeRun

works.

graalvm-filters's People

Contributors

mhalbritter avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.