Enjoy Sharing Technology!

Software,Develope,Devops, Security,TroubleShooting

Showing posts with label troubleshooting. Show all posts
Showing posts with label troubleshooting. Show all posts

Sunday, November 21, 2021

error: Microsoft Visual C++ 14.0 is required

For developers, they often pip install the packages they need. Most of the packages can be installed basically, but they will always encounter the problem of not being able to install the packages. The first step of pre-study learning motivation is killed by the installation package. . One of the most troubled is this question: error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual……

I tried a lot of methods on the Internet, but still did not fundamentally solve the problem. Generally, for this kind of package that cannot be installed by pip, one is to go to the Python installation package complete (https://www.lfd.uci.edu/~gohlke/pythonlibs/) to download the installation package with the corresponding suffix of .whl. Install.

How to install the installation package with the suffix .whl: Download the corresponding installation package with the suffix .whl and place it in the folder you specify, enter cmd,

pip install Scrapy-1.5.0-py2.py3-none-any.whl 

The other is that if the package with the suffix .whl is not found, or the .whl package is not successfully installed, it is generally installed on the operating system. It is very convenient to install these packages on the Linux system with pip, and no error will be reported.

To solve this problem fundamentally, you can refer to the following.

When running the code first, it says that the XXX package is not installed. If you encounter this problem, go to cmd, and the pip install installation error is reported:


It shows that the visual studio installer has stopped working. . .

I tried to download and install Microsoft Visual 2017 https://download.csdn.net/download/heyshheyou/10624594, but when I downloaded it and installed it, I reported an error as soon as I clicked to install it, and the visual studio installer has stopped working. I was completely speechless. . . . . Download different versions of visual studio installation are all reporting this error, it may be a program conflict.

There are also uninstalling .NET Framework files on the Internet, downloading a newest .NET Framework file; and also uninstalling all files beginning with Microsoft Visual:

I almost tried it, but fortunately I continued to find other solutions. Except in the end, there is no way to try, or reinstall the system. Do not reinstall the system as a last resort.
Troubleshoot blocked installation and uninstallation of .NET Framework
For the downloaded version of Microsoft Visual C++:
Visual Studio 2013 ---> 12
Visual Studio 2015 ---> 14
 Visual Studio 2017 ---> 15

Python3 is compiled with VC++14, python27 is compiled with VC++9, and the package to install python3 needs to be compiled and supported by VC++14 or above.
If you encounter an error: error: Microsoft Visual C++ 14.0 is required, please try the following solutions first.

Solution:

Installed Microsoft visual c++ 14.0, searched for a lot of packages, and finally found a Microsoft Visual C++ Build Tools 2015 :visualcppbuildtoos_full.exe .

Double-click visualcppbuildtools_full.exe, select the default, click install, and wait for about 10 minutes to complete the installation.

Finally, the installation is complete, check the control panel-program-uninstall program under an additional file Microsoft visual c++ Build Tools:

That is, the installation is successful.

As a result, go to pip in cmd to install the packages you need.






Share:

Wednesday, November 17, 2021

OutOfMemoryError(4): Metaspace

A series of articles on this topic:

JVM limits the maximum memory of Java programs, and this limitation can be changed by modifying/specifying startup parameters. Java divides the heap memory into multiple parts, as shown in the following figure:


[Java8 and above] The maximum value of these memory pools is specified by JVM startup parameters such as -Xmx and -XX:MaxMetaspaceSize. If not explicitly specified, it will be determined according to the platform type (OS version + JVM version) and the size of the physical memory. java.lang.OutOfMemoryError: The information expressed by the Metaspace error is: Metaspace has been used up.

Cause Analysis
If you are an old Java driver, you should be familiar with PermGen. But starting from Java 8, the memory structure has undergone major changes. Permgen is no longer used, but a new space is introduced: Metaspace. This change is based on many considerations, partly The reasons are listed as follows:

The specific size of the Permgen space is difficult to predict. Specifying a small size will cause java.lang.OutOfMemoryError: Permgen size error, and setting too many will cause waste.

In order to improve the performance of GC, the concurrent phase of the garbage collection process is no longer paused, and metadata is specifically traversed (specific iterators).

Deeply optimize the concurrent class unloading of the G1 garbage collector.

In Java 8, all the content in PermGen before has been moved to the Metaspace space. For example: class name, field, method, bytecode, constant pool, JIT optimized code, etc.

Metaspace usage is related to the number/size of classes loaded into memory by JVM. It can be said that the main reason for java.lang.OutOfMemoryError: Metaspace error is that the number of classes loaded into the memory is too large or the size is too large.

Example
Similar to PermGen , the amount of Metaspace space used has a lot to do with the number of classes loaded by the JVM. Here is a simple example:

public class Metaspace {
  static javassist.ClassPool cp = javassist.ClassPool.getDefault();
  public static void main(String[] args) throws Exception{
    for (int i = 0; ; i++) { 
      Class c = cp.makeClass("eu.plumbr.demo.Generated" + i).toClass();
    }
  }
}

As you can see, it is very simple to use the javassist tool library to generate a class. In the for loop, a lot of classes are dynamically generated, and these classes are finally loaded into the Metaspace.

Execute this code, as more and more classes are generated, it will eventually fill up the Metaspace space, throwing java.lang.OutOfMemoryError: Metaspace. On Mac OS X, in the Java 1.8.0_05 environment, if the startup is set Parameter -XX:MaxMetaspaceSize=64m, JVM will hang after about 70,000 classes are loaded.

solution:

If an OutOfMemoryError related to Metaspace is thrown, the first solution is to increase the size of Metaspace. Use the following startup parameters:

-XX:MaxMetaspaceSize=512m

Here, the maximum value of Metaspace is set to 512MB, if it is not used up, OutOfMemoryError will not be thrown.

There is a seemingly simple solution, which is to directly remove the size limit of Metaspace. But it should be noted that there is no limit to the size of Metaspace memory. If the physical memory is insufficient, it may cause memory swapping, which will seriously affect system performance. In addition, it may cause problems such as native memory allocation failure.

In modern application clusters, it is better to let the application node go down than to respond slowly.

If you don't want to receive an alarm, you can hide the java.lang.OutOfMemoryError: Metaspace error message like an ostrich. But this will not really solve the problem, it will only delay the outbreak of the problem. If there is a memory leak, please refer to these articles and look for a solution carefully.
Share:

OutOfMemoryError(3): Permgen space

 A series of articles on this topic:

Note: Permgen (permanent generation) belongs to the concept of JDK1.7 and previous versions; in order to adapt to the development of Java programs, JDK8 and later versions use less restrictive MetaSpace instead

JVM limits the maximum memory usage of Java programs, which can be configured through startup parameters. The heap memory of Java is divided into multiple areas, as shown in the following figure:



The maximum value of these areas is specified by the JVM startup parameters -Xmx and -XX:MaxPermSize. If not explicitly specified, it is determined according to the operating system platform and the size of the physical memory.

java.lang.OutOfMemoryError: PermGen space error message means: Permanent Generation (Permanent Generation) memory area is full.

Cause Analysis

Let's first look at what PermGen is used for.

In JDK1.7 and earlier versions, permanent generation is mainly used to store class definitions loaded/cached in memory, including class names, fields, methods and bytecodes (method bytecode); and constant pool information; classes associated with object arrays/type arrays, and class information optimized by the JIT compiler.

It is easy to see that the usage of PermGen is related to the number/size of classes loaded into memory by the JVM. It can be said that the main reason for java.lang.OutOfMemoryError: PermGen space is that the number of classes loaded into the memory is too large or the size is too large.

The simplest example

We know that the usage of PermGen space has a lot to do with the number of classes loaded by the JVM. The following code demonstrates this situation:

import javassist.ClassPool;

public class MicroGenerator {

  public static void main(String[] args) throws Exception {

    for (int i = 0; i < 100_000_000; i++) {

      generate("eu.plumbr.demo.Generated" + i);

    }

  }

  public static Class generate(String name) throws Exception {

    ClassPool pool = ClassPool.getDefault();

    return pool.makeClass(name).toClass();

  }

}

This code generates many classes dynamically in the for loop. As you can see, it is very simple to use the javassist tool class to generate a class.

Executing this code will generate a lot of new classes and load them into memory. As more and more classes are generated, they will fill up the Permgen space, and then throw a java.lang.OutOfMemoryError: Permgen space error, of course , Other types of OutOfMemoryError may also be thrown.

To see the effect quickly, you can add appropriate JVM startup parameters, such as: -Xmx200M -XX:MaxPermSize=16M and so on.

OutOfMemoryError during Redeploy

Note: If Tomcat generates a warning during development, you can ignore it. It is recommended not to redploy in the production environment, just close/or Kill related JVM directly, and then start from the beginning.

The following situation is more common. When redeploying a web application, it is likely to cause a java.lang.OutOfMemoryError: Permgen space error. It stands to reason that when redeploying, a container such as Tomcat will use a new classloader to load a new class. Let the garbage collector clean up the previous classloader (along with the loaded class).

But the actual situation may not be optimistic. Many third-party libraries, as well as some restricted shared resources, such as threads, JDBC drivers, and file system handles (handles), will cause the previous classloader to be unable to be completely uninstalled. Then in redeploy, The previous class still resides in PermGen, and each redeployment will generate tens of MB or even hundreds of MB of garbage.

Suppose that when an application is started, the JDBC driver is loaded through the initialization code to connect to the database. According to the JDBC specification, the driver will register itself to java.sql.DriverManager, that is, add an instance of itself to a static in DriverManager area.

Then, when the application is uninstalled from the container, java.sql.DriverManager still holds a JDBC instance (Tomcat often warns), and the JDBC driver instance holds a java.lang.Classloader instance, so the garbage collector has no way. Reclaim the corresponding memory space.

The java.lang.ClassLoader instance holds all the loaded classes, usually tens/hundreds of MB of memory. As you can see, redeploy will take up another piece of PermGen space of the same size. After multiple redeploys, it will cause java.lang.OutOfMemoryError: PermGen space error. In the log file, you should see related error messages.

solution

1. Solve the OutOfMemoryError generated when the program starts

When the program starts, if PermGen is exhausted and an OutOfMemoryError is generated, it is easy to solve. Increase the size of PermGen so that the program has more memory to load the class. Modify the -XX:MaxPermSize startup parameter, similar to the following:

java -XX:MaxPermSize=512m com.yourcompany.YourClass

The above configuration allows the JVM to use the maximum PermGen space of 512MB, if it is not enough, an OutOfMemoryError will be thrown.

2. Solve the OutOfMemoryError generated during redeploy

We can perform heap dump analysis-after redeploy, perform a heap dump, similar to the following:
jmap -dump:format=b,file=dump.hprof <process-id>

Then use a heap dump analyzer (such as the powerful Eclipse MAT) to load the dump file. Find out the duplicate classes, especially the class corresponding to the classloader. You may need to compare all the classloaders to find the one currently in use.

Eclipse MAT  official website download address: http://www.eclipse.org/mat/downloads.php

For an inactive classloader (inactive classloader), you need to determine the shortest path GC root first, and see which one prevents it from being recycled by the garbage collector. In this way, you can find the source of the problem. If it is a third-party library, Then you can search Google/StackOverflow to find the solution. If it is your own code problem, you need to dereference at the right time.

3. Solve OutOfMemoryError generated during runtime
If an OutOfMemoryError occurs during operation, first confirm whether the GC can unload the class from PermGen. The official JVM is quite conservative in this regard (after loading a class, it has been allowed to reside in memory, even if the class is no longer used). However, modern applications will dynamically create a large number of The life cycle of these classes is basically very short, and the old version of JVM cannot handle these problems well. Then we need to allow the JVM to uninstall the class. Use the following startup parameters:

-XX:+CMSClassUnloadingEnabled

By default, the value of CMSClassUnloadingEnabled is false, so it needs to be specified explicitly. After enabling, GC will clean up PermGen and uninstall useless classes. Of course, this option only takes effect when UseConcMarkSweepGC is set. If you use ParallelGC, or Serial GC, you need to switch to CMS:
-XX:+UseConcMarkSweepGC

If it is determined that the class can be unloaded, if OutOfMemoryError still exists, then a heap dump analysis is required, similar to the following command:
jmap -dump:file=dump.hprof,format=b <process-id> 

Then load the heap dump through a heap dump analyzer (such as Eclipse MAT). Find the heaviest classloader, that is, the one with the largest number of loaded classes. Compare the class loader with the loaded class and the number of corresponding instances, find the top part, and analyze it one by one.

For each suspected class, you need to manually trace to the code that generates these classes to locate the problem.





Share:

OutOfMemoryError(2): GC overhead limit exceeded

A series of articles on this topic:

The Java runtime environment has a built-in garbage collection (GC) module. Many programming languages of the previous generation did not have an automatic memory recovery mechanism, and programmers were required to manually write code to allocate and release memory to reuse heap memory.

In a Java program, you only need to care about memory allocation. If a block of memory is no longer used, the Garbage Collection module will automatically clean it up. For the detailed principle of GC, please refer to the GC performance optimization series of articles. Generally speaking, the garbage collection algorithm built in JVM can handle most business scenarios.

java.lang.OutOfMemoryError: GC overhead limit exceeded The reason this happens is that the program basically uses up all the available memory, and the GC can't clean it up.

Cause Analysis:

JVM throws java.lang.OutOfMemoryError: GC overhead limit exceeded error is a signal: the proportion of time to perform garbage collection is too large, and the amount of effective calculation is too small. By default, if the time spent in GC exceeds 98%, And if the memory reclaimed by GC is less than 2%, the JVM will throw this error.

Note that the java.lang.OutOfMemoryError: GC overhead limit exceeded error is only thrown in extreme cases where less than 2% of the GC has been recycled for multiple consecutive times. What happens if the GC overhead limit error is not thrown? That is, the memory cleaned up by the GC will fill up again soon, forcing the GC to execute again. This forms a vicious circle, the CPU usage is always 100%, and the GC But there is no result. System users will see that the system freezes-an operation that used to take only a few milliseconds, now takes several minutes to complete.

This is also a good case of the fast failure principle.

Example:
The following code adds data to the Map in an infinite loop. This will result in a "GC overhead limit exceeded" error:

public class OOM {

    static final int SIZE=2*1024*1024;

    public static void main(String[] a) {

        int[] i = new int[SIZE];

    }

}

Configure JVM parameters: -Xmx12m. The error message generated during execution is as follows:

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded

    at java.util.Hashtable.addEntry(Hashtable.java:435)

    at java.util.Hashtable.put(Hashtable.java:476)

    at com.cncounter.rtime.TestWrapper.main(TestWrapper.java:11)

The error message you encounter is not necessarily the same. Indeed, the JVM parameters we executed are:

java -Xmx12m -XX:+UseParallelGC TestWrapper

Soon I saw the java.lang.OutOfMemoryError: GC overhead limit exceeded error message. But in fact, this example is a bit tricky. Because of different heap memory sizes, different GC algorithms are used, the error messages generated are different. For example, when the Java heap memory is set to 10M:

java -Xmx10m -XX:+UseParallelGC TestWrapper

The error message in DEBUG mode is as follows:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

    at java.util.Hashtable.rehash(Hashtable.java:401)

    at java.util.Hashtable.addEntry(Hashtable.java:425)

    at java.util.Hashtable.put(Hashtable.java:476)

    at com.cncounter.rtime.TestWrapper.main(TestWrapper.java:11)

Try to modify the parameters, execute to see the specifics. The error message and stack information may be different.

The java.lang.OutOfMemoryError: Java heap space error message is thrown when the Map is rehashing. If you use other garbage collection algorithms, such as -XX:+UseConcMarkSweepGC, or -XX:+UseG1GC, the error will be caused by the default exception handler Capture, but there is no stacktrace information, because there is no way to fill the stacktrace information when creating an Exception.

For example configuration:

-Xmx12m -XX:+UseG1GC

Running in Win7x64, Java8 environment, the error message generated is:

Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"

It is recommended that readers modify the memory configuration and test the garbage collection algorithm.

These real cases show that under resource constraints, it is impossible to accurately predict which specific reasons a program will die of. Therefore, in the face of such errors, a specific error processing sequence cannot be bound.

solution:

There is a solution to deal with the problem, just don't want to throw "java.lang.OutOfMemoryError: GC overhead limit exceeded" error message, then add the following startup parameters

// not recommendation

-XX:-UseGCOverheadLimit

We strongly recommend not to specify this option: because it does not really solve the problem, it can only postpone the occurrence of out of memory errors a little bit, and other processing must be done at the end. Specifying this option will cover up the original java.lang.OutOfMemoryError: GC overhead limit exceeded error and turn it into a more common java.lang.OutOfMemoryError: Java heap space error message.

Note: Sometimes the cause of the GC overhead limit error is caused by insufficient heap memory allocated to the JVM. In this case, you only need to increase the heap memory size.

In most cases, increasing the heap memory does not solve the problem. For example, there is a memory leak in the program, and increasing the heap memory can only delay the time of java.lang.OutOfMemoryError: Java heap space error.

Of course, increasing the heap memory may also increase the time of GC pauses, thereby affecting the throughput or delay of the program.

If you want to solve the problem fundamentally, you need to troubleshoot the code related to memory allocation. Simply put, you need to answer the following questions:

Which type of object takes up the most memory?

These objects are allocated in which part of the code.

To figure this out, it may take several days. The following is the general process:

Obtain the permission to perform a heap dump on the production server. "Dump" is a snapshot of the heap memory, which can be used for subsequent memory analysis. These snapshots may contain confidential information, such as passwords, credit card accounts, etc., so sometimes, due to corporate security restrictions, it is necessary to obtain the production environment Heap dumping is not easy.

Perform a heap dump at the appropriate time. Generally speaking, memory analysis needs to compare multiple heap dump files. If the timing is not right, it may be a "scrap" snapshot. In addition, every time a heap dump is executed, the JVM will be "freeze" ", so in the production environment, you can't perform too many dump operations, otherwise the system is slow or stuck, and your troubles will be big.

Use another machine to load the Dump file. If the JVM memory in question is 8GB, the machine memory for analyzing Heap Dump generally needs to be greater than 8GB. Then open the dump analysis software (we recommend Eclipse MAT, of course, you can also use other tools).

Detect the GC roots that occupy the most memory in the snapshot. For details, please refer to: Solving OutOfMemoryError (part 6) – Dump is not a waste. This may be a bit difficult for novices, but it will also deepen your understanding of the heap memory structure and navigation mechanism.

Next, find out the code that may allocate a large number of objects. If you are very familiar with the entire system, you may be able to locate the problem very quickly. If you are unlucky, you will have to work overtime to investigate.







Share:

OutOfMemoryError(1): Java heap space

A series of articles on this topic:

Each Java program can only use a certain amount of memory, and this limitation is determined by the startup parameters of the JVM. The more complicated situation is that the memory of Java programs is divided into two parts: Heap space and Permanent Generation (Permgen):

The maximum memory size of these two areas is specified by the JVM startup parameters -Xmx and -XX:MaxPermSize. If not explicitly specified, it is determined according to the platform type (OS version + JVM version) and the size of the physical memory. If when creating a new object, the space in the heap memory is not enough to store the newly created object, it will cause java.lang.OutOfMemoryError: Java heap space error. No matter there is no free physical memory on the machine, as long as the heap memory usage reaches the maximum memory limit, a java.lang.OutOfMemoryError: Java heap space error will be thrown.


Cause Analysis:

The reason for the java.lang.OutOfMemoryError: Java heap space error is often similar to stuffing the object of the XXL number into the Java heap space of the S number. In fact, if you know the reason, it's easy to solve, right? Just increase the size of the heap memory, and the program can run normally. In addition, there are some more complicated situations, mainly caused by code problems:
The amount of visits/data exceeded expectations. When designing an application system, there is generally a definition of "capacity", so many machines are deployed to process a certain amount of data/business. If the number of visits soars suddenly and exceeds the expected threshold, which is similar to a pinpoint-shaped map in the time coordinate system, then the program is likely to be stuck during the time period when the peak is located, and java.lang.OutOfMemoryError: Java heap space error is triggered. .
Memory leak. This is also a common situation. Due to some errors in the code, the system occupies more and more memory. If there is a memory leak in a certain method/a certain piece of code, every time it is executed, it will take up more memory (there are more garbage objects) . As the running time goes by, the leaked object consumes all the memory in the heap, then the java.lang.OutOfMemoryError: Java heap space error broke out.

A very simple example:

The following code is very simple. The program tries to allocate an int array with a capacity of 2M. If the startup parameter -Xmx12m is specified, then java.lang.OutOfMemoryError: Java heap space error will occur. As long as the parameter is slightly modified to -Xmx13m, the error will no longer occur.

publicclass OOM {static final int SIZE=2*1024*1024; publicstaticvoidmain(String[] a) {int[] i = newint[SIZE]; }}

public class OOM {
    static final int SIZE=2*1024*1024;
    public static void main(String[] a) {
        int[] i = new int[SIZE];
    }
}

Memory leak example:

This example is more realistic. In Java, when creating a new object, such as Integer num = new Integer(5);, there is no need to manually allocate memory. Because the JVM automatically encapsulates and handles memory allocation. During the execution of the program, the JVM will check if necessary which objects are still in use in the memory, and those objects that are no longer used will be discarded and the memory occupied by them will be discarded. Recycle and reuse. This process is called garbage collection. The module responsible for garbage collection in the JVM is called the garbage collector (GC).

Java's automatic memory management relies on GC. GC scans the memory area over and over again and deletes unused objects. Simply put, memory leaks in Java are those logically no longer used objects, but they are not garbage collected The program is killed. As a result, garbage objects continue to occupy the heap memory, gradually accumulate, and finally cause java.lang.OutOfMemoryError: Java heap space error.

It is easy to write a BUG program to simulate a memory leak:

import java.util.*;

public class KeylessEntry {

    static class Key {
        Integer id;

        Key(Integer id) {
        this.id = id;
        }

        @Override
        public int hashCode() {
        return id.hashCode();
        }
     }

    public static void main(String[] args) {
        Map m = new HashMap();
        while (true){
        for (int i = 0; i < 10000; i++){
           if (!m.containsKey(new Key(i))){
               m.put(new Key(i), "Number:" + i);
           }
        }
        System.out.println("m.size()=" + m.size());
        }
    }
}

At a glance, you may think that there is no problem, because this caches up to 10,000 elements! But a closer examination will find that the Key class only rewrites the hashCode() method, but does not rewrite the equals() method, so it will continue Add more keys to the HashMap.
As time goes by, there will be more and more "cached" objects. When the leaked objects occupy all the heap memory and the GC can't clean it up, a java.lang.OutOfMemoryError: Java heap space error will be thrown.
The solution is simple, implement the equals() method appropriately in the Key class:
@Override public boolean equals(Object o) { boolean response = false; if (o instanceof Key) { response = (((Key)o).id).equals(this.id); } return response; }
To be honest, when looking for the real cause of a memory leak, you may die many, many brain cells.

A scene in SpringMVC

In order to be easily compatible with the code migrated from Struts2 to SpringMVC, the request is directly obtained in the Controller.

So in the ControllerBase class, the request object held by the current thread is cached through ThreadLocal:

public abstract class ControllerBase {

    private static ThreadLocal<HttpServletRequest> requestThreadLocal = new ThreadLocal<HttpServletRequest>();

    public static HttpServletRequest getRequest(){
        return requestThreadLocal.get();
    }
    public static void setRequest(HttpServletRequest request){
        if(null == request){
        requestThreadLocal.remove();
        return;
        }
        requestThreadLocal.set(request);
    }
}

Then in the SpringMVC Interceptor implementation class, in the preHandle method, save the request object to ThreadLocal:


public class LoginCheckInterceptor implements HandlerInterceptor {
    private List<String> excludeList = new ArrayList<String>();
    public void setExcludeList(List<String> excludeList) {
        this.excludeList = excludeList;
    }

    private boolean validURI(HttpServletRequest request){
        String uri = request.getRequestURI();
        Iterator<String> iterator = excludeList.iterator();
        while (iterator.hasNext()) {
        String exURI = iterator.next();
        if(null != exURI && uri.contains(exURI)){
            return true;
        }
        }
        LoginUser user = ControllerBase.getLoginUser(request);
        if(null != user){
        return true;
        }
        return false;
    }

    private void initRequestThreadLocal(HttpServletRequest request){
        ControllerBase.setRequest(request);
        request.setAttribute("basePath", ControllerBase.basePathLessSlash(request));
    }
    private void removeRequestThreadLocal(){
        ControllerBase.setRequest(null);
    }

    @Override
    public boolean preHandle(HttpServletRequest request,
        HttpServletResponse response, Object handler) throws Exception {
        initRequestThreadLocal(request);
        if (false == validURI(request)) {
        throw new NeedLoginException();
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request,
        HttpServletResponse response, Object handler, ModelAndView modelAndView)
        throws Exception {
        removeRequestThreadLocal();
    }

    @Override
    public void afterCompletion(HttpServletRequest request,
        HttpServletResponse response, Object handler, Exception ex)
        throws Exception {
        removeRequestThreadLocal();
    }
}

In the postHandle and afterCompletion methods, clean up the request object in ThreadLocal.

But in actual use, business developers set a large object (such as a List occupying about 200MB of memory) as the Attributes of the request and pass it to the JSP.

If an exception may occur in the JSP code, SpringMVC's postHandle and afterCompletion methods will not be executed.

Thread scheduling in Tomcat may not be able to schedule the thread that throws the exception, so ThreadLocal always holds the request. As the running time goes by, the available memory is filled up, and the Full GC is being executed all the time, and the system is directly stuck.

Subsequent amendments: Through Filter, clean up ThreadLocal in the finally block.

@WebFilter(value="/*", asyncSupported=true)
public class ClearRequestCacheFilter implements Filter{

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
            ServletException {
        clearControllerBaseThreadLocal();
        try {
            chain.doFilter(request, response);
        } finally {
            clearControllerBaseThreadLocal();
        }
    }

    private void clearControllerBaseThreadLocal() {
        ControllerBase.setRequest(null);
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}
    @Override
    public void destroy() {}
}

ThreadLocal can be used, but there must be a controlled release measure, usually a try-finally code form.

Explanation: In the Controller of SpringMVC, the request can be injected through @Autowired. The actual injection is an HttpServletRequestWrapper object, and the current request is also called through the ThreadLocal mechanism during execution.

Conventional way: Just receive the request parameter directly in the controller method.
Share:

Search This Blog

Weekly Pageviews

Translate