`
Donald_Draper
  • 浏览: 999357 次
社区版块
存档分类
最新评论

SelectorImpl分析

    博客分类:
  • NIO
阅读更多
Channel接口定义:http://donald-draper.iteye.com/blog/2369111
AbstractInterruptibleChannel接口定义:http://donald-draper.iteye.com/blog/2369238
SelectableChannel接口定义:http://donald-draper.iteye.com/blog/2369317
SelectionKey定义:http://donald-draper.iteye.com/blog/2369499
SelectorProvider定义:http://donald-draper.iteye.com/blog/2369615
AbstractSelectableChannel定义:http://donald-draper.iteye.com/blog/2369742
NetworkChannel接口定义:http://donald-draper.iteye.com/blog/2369773
ServerSocketChannel定义:http://donald-draper.iteye.com/blog/2369836
Selector定义:http://donald-draper.iteye.com/blog/2370015
AbstractSelector定义:http://donald-draper.iteye.com/blog/2370138
上一篇我们看了一下AbstractSelector,主要是维护取消key集合,和key的反注册。
取消的key放在一个set集合中,对集合进行添加操作时,必须同步取消key set集合。
反注册选择key完成的实际工作是,将key,从key对应的通道的选择key数组(这个我们在选择通道相关文章中有讲)中移除。
今天来看一下SelectorImpl
abstract class SelectorImpl extends AbstractSelector
{
    protected Set selectedKeys;//就绪key集合,即已经操作事件准备就绪的选择key
    protected HashSet keys;//与选择器关联的key集合
    private Set publicKeys;//外部访问key集合的代理
    private Set publicSelectedKeys;//外部访问就绪key集合代理
        protected SelectorImpl(SelectorProvider selectorprovider)
    {
        super(selectorprovider);
	//初始化就绪key集合和key集合
        keys = new HashSet();
        selectedKeys = new HashSet();
        if(Util.atBugLevel("1.4"))
        {
            publicKeys = keys;
            publicSelectedKeys = selectedKeys;
        } else
        {
	    //将当前key集合包装成不可修改的集合publicKes
            publicKeys = Collections.unmodifiableSet(keys);
	    //将就绪key集合包装成容量固定的集合
            publicSelectedKeys = Util.ungrowableSet(selectedKeys);
        }
    }
}

再来看构造的在bugLevel为1.4的情况下,就绪key和key集合的代理集合初始化分2步看:
1.BugLevel为1.4
if(Util.atBugLevel("1.4"))
    {
        publicKeys = keys;
        publicSelectedKeys = selectedKeys;
    }

2.BugLevel不为1.4
 else
        {
	    //将当前key集合包装成不可修改的集合publicKes
            publicKeys = Collections.unmodifiableSet(keys);
	    //将就绪key集合包装成容量固定的集合
            publicSelectedKeys = Util.ungrowableSet(selectedKeys);
        }


//Util,nio通道工具类,从定义来看应该是缓冲区工具
class Util
{
    private static ThreadLocal localSelector = new ThreadLocal();
    private static ThreadLocal localSelectorWrapper = new ThreadLocal();
    private static Unsafe unsafe = Unsafe.getUnsafe();
    private static int pageSize = -1;
    private static volatile Constructor directByteBufferConstructor = null;
    private static volatile Constructor directByteBufferRConstructor = null;
    private static volatile String bugLevel = null;
    private static boolean loaded = false;
    static final boolean $assertionsDisabled = !sun/nio/ch/Util.desiredAssertionStatus();
    static 
    {
        //通道IO工具
        TEMP_BUF_POOL_SIZE = IOUtil.IOV_MAX;
    }
}




//通道IO工具
class IOUtil
{
    ...,这里省略一些方法,用到的时候再讲,主要是读写Socket
    static native boolean randomBytes(byte abyte0[]);
    static native long makePipe(boolean flag);
    static native boolean drain(int i)
        throws IOException;
    //配置阻塞模式
    static native void configureBlocking(FileDescriptor filedescriptor, boolean flag)
        throws IOException;
   //获取文件描述(Socket)的值
    static native int fdVal(FileDescriptor filedescriptor);
    //设置文件描述的值
    static native void setfdVal(FileDescriptor filedescriptor, int i);
    static native int iovMax();
    static native void initIDs();
    static final int IOV_MAX = iovMax();
    static final boolean $assertionsDisabled = !sun/nio/ch/IOUtil.desiredAssertionStatus();
    static 
    {
        Util.load();
    }
}




上面两个工具类我们在以后遇到的时候再讲,粗略地看一了,Util为nio的缓冲区工具,IOUtil为通道IO工具。
再回到就绪key和key集合的代理集合初始化的第一点:
if(Util.atBugLevel("1.4"))
    {
        publicKeys = keys;
        publicSelectedKeys = selectedKeys;
    } 

//Util
static boolean atBugLevel(String s)
    {
        if(bugLevel == null)
        {
            if(!VM.isBooted())
	        //如果虚拟器没启动,则返回false
                return false;
	    //在当前线程访问控制权限的环境下,获取系统属性sun.nio.ch.bugLevel
            String s1 = (String)AccessController.doPrivileged(new GetPropertyAction("sun.nio.ch.bugLevel"));
            bugLevel = s1 == null ? "" : s1;
        }
        return bugLevel.equals(s);
    }

关于bugLevel的相关连接:
Sun GlassFish Enterprise Server v3 Release Notes:
https://docs.oracle.com/cd/E19226-01/820-7688/6niu9p8i3/index.html
Use of the bug level variable  -Dsun.nio.ch.bugLevel=1.4:
https://community.oracle.com/thread/1240510
从上面来看bugLevel对应的是虚拟机启动的参数配置sun.nio.ch.bugLevel,
由于在nio包在1.4时加入,包中有一个bug问题,
"java.lang.NullPointerException
at sun.nio.ch.Util.atBugLevel(Util.java:326)
at sun.nio.ch.SelectorImpl.<init>(SelectorImpl.java:40)
at sun.nio.ch.WindowsSelectorImpl.<init>(WindowsSelectorImpl.java:104)
at sun.nio.ch.WindowsSelectorProvider.openSelector(WindowsSelectorProvider.java:26)
at java.nio.channels.Selector.open(Selector.java:209)

这个bug在jdk1.5中存在,直到jdk1.7才修复。
从上面的这些信息来看bugLevel应该是标记nio存在bug情况的jdk版本,
如果有不同的理解,可以给我留言。

atBugLevel方法有两点关注:
a.判断虚拟机是否启动
b.获取虚拟机参数sun.nio.ch.bugLevel
先看第一点
a.判断虚拟机是否启动
package sun.misc;
import java.util.Properties;

// Referenced classes of package sun.misc:
//            OSEnvironment, VMNotification

public class VM
{
    public VM()
    {
    }
    //下面这些变量,暂时不选关注,以后有时间,
    //我们在看,只需要看到的虚拟机是否启动booted
    private static boolean suspended = false;
    /**
     * @deprecated Field STATE_GREEN is deprecated
     */
    public static final int STATE_GREEN = 1;
    /**
     * @deprecated Field STATE_YELLOW is deprecated
     */
    public static final int STATE_YELLOW = 2;
    /**
     * @deprecated Field STATE_RED is deprecated
     */
    public static final int STATE_RED = 3;
    private static volatile boolean booted = false;
    private static long directMemory = 67108864L;/64M
    private static boolean pageAlignDirectMemory;
    private static boolean defaultAllowArraySyntax;
    private static boolean allowArraySyntax;
    private static final Properties savedProps = new Properties();
    private static volatile int finalRefCount = 0;
    private static volatile int peakFinalRefCount = 0;
    private static final int JVMTI_THREAD_STATE_ALIVE = 1;
    private static final int JVMTI_THREAD_STATE_TERMINATED = 2;
    private static final int JVMTI_THREAD_STATE_RUNNABLE = 4;
    private static final int JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 1024;
    private static final int JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 16;
    private static final int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 32;
    static 
    {
        defaultAllowArraySyntax = false;
        allowArraySyntax = defaultAllowArraySyntax;
        initialize();
    }
    private static native void initialize();
    public static void booted()
    {
        booted = true;
    }
    //VM是否启动
    public static boolean isBooted()
    {
        return booted;
    }
}

b.获取虚拟机参数sun.nio.ch.bugLevel
//GetPropertyAction,获取系统属性Action
package sun.security.action;
import java.security.PrivilegedAction;
public class GetPropertyAction
    implements PrivilegedAction
{
    private String theProp;
    private String defaultVal;
    public GetPropertyAction(String s)
    {
        theProp = s;
    }
    public GetPropertyAction(String s, String s1)
    {
        theProp = s;
        defaultVal = s1;
    }
    //获取系统属性,为空返回默认属性值
    public String run()
    {
        String s = System.getProperty(theProp);
        return s != null ? s : defaultVal;
    }
    public volatile Object run()
    {
        return run();
    }
}

从上面一段分析可以看出,如果nio包的JDK版本存在bug问题,则就绪key和key集合的代理集合直接引用就绪key和key集合。
再回到就绪key和key集合的代理集合初始化的第二点:
2.BugLevel不为1.4
else
   {
      //将当前key集合包装成不可修改的集合publicKes
       publicKeys = Collections.unmodifiableSet(keys);
      //将就绪key集合包装成容量固定的集合
       publicSelectedKeys = Util.ungrowableSet(selectedKeys);
   }

将当前key集合包装成不可修改的集合publicKes,这个就不用说了,我们以前在java的集合综述篇中有说。我们主要将下一点将就绪key集合包装成容量固定的集合,
//Util
 static Set ungrowableSet(Set set)
    {
        return new Set(set) {
             final Set val$s;
            {
                s = set;
                super();
            }
            public int size()
            {
                return s.size();
            }
            public boolean isEmpty()
            {
                return s.isEmpty();
            }
            public boolean contains(Object obj)
            {
                return s.contains(obj);
            }
            ...
            public Iterator iterator()
            {
                return s.iterator();
            }
            ...
            public void clear()
            {
                s.clear();
            }

            public boolean remove(Object obj)
            {
                return s.remove(obj);
            }

            public boolean containsAll(Collection collection)
            {
                return s.containsAll(collection);
            }

            public boolean removeAll(Collection collection)
            {
                return s.removeAll(collection);
            }

            public boolean retainAll(Collection collection)
            {
                return s.retainAll(collection);
            }
	    //集合不可添加元素
            public boolean add(Object obj)
            {
                throw new UnsupportedOperationException();
            }
            public boolean addAll(Collection collection)
            {
                throw new UnsupportedOperationException();
            }
        };
    }

从上面来看
Util.ungrowableSet(Set set)方法,对集合Set进行简单的封装,移除迭代,比较等操作
直接委托给原始的Set集合,只是封装后的集合不允许添加元素,但可以移除,查询操作。
这段话是不是很熟悉,在Selector定义的文章,Java Doc有说就绪key集合SelectedKeys的
这些属性。
小节一下就绪key和key集合的初始化:
如果nio包的JDK版本存在bug问题,则就绪key和key集合的代理集合直接引用就绪key和key集合。否则将当前key集合包装成不可修改的代理集合publicKes,将就绪key集合包装成容量固定的集合publicSelectedKeys

再来看获取就绪key和key集合
//key集合
public Set keys()
 {
     if(!isOpen() && !Util.atBugLevel("1.4"))
         throw new ClosedSelectorException();
     else
         return publicKeys;
 }

//就绪key
 public Set selectedKeys()
 {
     if(!isOpen() && !Util.atBugLevel("1.4"))
         throw new ClosedSelectorException();
     else
         return publicSelectedKeys;
 }

从上面来看,其他线程获取选择器的就绪key和key集合,实际上返回的是
key集合的代理publicKeys和就绪key集合的代理publicSelectedKeys。

再来看几个选择操作:
 public int select()
        throws IOException
    {
        //委托给select(long l)
        return select(0L);
    }
 public int select(long l)
        throws IOException
    {
        if(l < 0L)
	    //负数抛出异常
            throw new IllegalArgumentException("Negative timeout");
        else
	    //委托给lockAndDoSelect(long l)
            return lockAndDoSelect(l != 0L ? l : -1L);
    }
 public int selectNow()
        throws IOException
    {
         //委托给lockAndDoSelect(long l)
        return lockAndDoSelect(0L);
    }

再来看lockAndDoSelect方法:
private int lockAndDoSelect(long l)
        throws IOException
    {
        SelectorImpl selectorimpl = this;
        JVM INSTR monitorenter ;
        if(!isOpen())
            throw new ClosedSelectorException();
	//取得key集合代理
        Set set = publicKeys;
        JVM INSTR monitorenter ;
	//取得就绪key代理
        Set set1 = publicSelectedKeys;
        JVM INSTR monitorenter ;
	//实际选择操作代理
        return doSelect(l);
        Exception exception;
        exception;
        throw exception;
        Exception exception1;
        exception1;
        throw exception1;
        Exception exception2;
        exception2;
        throw exception2;
    }

在上面的方法中有一些:
 JVM INSTR monitorenter ;
 ...
 Exception exception;
 exception;
 throw exception;

这个是什么意思,不是很理解,找了一下资料
JVM INSTR:
https://coderanch.com/t/385088/java/JVM-INSTR
JVM INSTR monitorenter and JVM INSTR monitorexit:
http://stackoverflow.com/questions/9547975/jvm-instr-monitorenter-and-jvm-instr-monitorexit
按照资料的说法,上述的这标记是JVM规范,实际相当与同步语句块(synchronized);
JVM INSTR monitorenter进入同步,JVM INSTR monitorexit退出同步;
Exception exception;
exception;
throw exception;

相等于
catch(Exception exception)
{
    throw exception;
}

再来看实际选择操作
//实际选择操作
return doSelect(l);

//待父类扩展,我们在下一篇文章中再看
protected abstract int doSelect(long l)
        throws IOException;

select方法的3中操作形式,实际上委托给为lockAndDoSelect方法,方法实际上是同步的,
可安全访问,获取key集合代理publicKeys和就绪key代理集合publicSelectedKeys,然后交给
doSelect(long l)方法,这个方法为抽象方法,待子类扩展。
在AbstractSelector的close方法,最有调用了implCloseSelector;
下面来看关闭选择器的实际操作implCloseSelector
 public void implCloseSelector()
        throws IOException
    {
        wakeup();
        synchronized(this)
        {
            synchronized(publicKeys)
            {
                synchronized(publicSelectedKeys)
                {
                    implClose();
                }
            }
        }
    }

  
 //唤醒等待选择操作的线程,待子类扩展
    public abstract Selector wakeup();

   
//完成实际的关闭选择器工作
    protected abstract void implClose()
        throws IOException;

从implCloseSelector方法来看,首先唤醒等待选择操作的线程,唤醒方法wakeup待实现,
同步选择器,就绪key和key集合的代理publicKeys,publicSelectedKeys,调用implClose完成实际的关闭通道工作,待子类实现。
再来看注册通道到选择器:
 protected final SelectionKey register(AbstractSelectableChannel abstractselectablechannel, int i, Object obj)
    {
        if(!(abstractselectablechannel instanceof SelChImpl))
	    //如果可选择通道不是SelChImpl的实例,则抛出IllegalSelectorException
            throw new IllegalSelectorException();
	//更具可选择通道和选择器创建选择key
        SelectionKeyImpl selectionkeyimpl = new SelectionKeyImpl((SelChImpl)abstractselectablechannel, this);
        //设置key的附加物
	selectionkeyimpl.attach(obj);
	//同步key集合代理
        synchronized(publicKeys)
        {
	    //完成实际的注册工作
            implRegister(selectionkeyimpl);
        }
	//设置key的兴趣事件集
        selectionkeyimpl.interestOps(i);
        return selectionkeyimpl;
    }

  
 //待子类实现
    protected abstract void implRegister(SelectionKeyImpl selectionkeyimpl);

从可选通道注册方法来看,首先注册的通道必须是AbstractSelectableChannel类型,并且是SelChImpl实例。更具可选择通道和选择器构造选择key,设置选择key的附加物,同步key集合代理,调用implRegister方法完成实际的注册工作,implRegister方法待子类实现。
//再来看处理反注册队列,现在看,还不能完全理解此方法的意思,在后面的文章,
我们会继续说,现在不能能完全看到,只以目前的能力,阅读以下代码,理解多少是多少,
因为里面牵涉到JVM规范,不知道说的正不正确,我只以目前的能力来阅读代码。
 void processDeregisterQueue()
        throws IOException
    {
        Set set = cancelledKeys();//获取取消key集合
        Set set1 = set;
        JVM INSTR monitorenter ;//进入同步语句块
        Iterator iterator;
        if(set.isEmpty())
            break MISSING_BLOCK_LABEL_110;
        iterator = set.iterator();
_L2://遍历取消key集合
        SelectionKeyImpl selectionkeyimpl;
        if(!iterator.hasNext())
            break; /* Loop/switch isn't completed */
        selectionkeyimpl = (SelectionKeyImpl)iterator.next();
        try
        {
	    //完成实际取消选择key的反注册
            implDereg(selectionkeyimpl);
        }
        catch(SocketException socketexception)
        {
            IOException ioexception = new IOException("Error deregistering key");
            ioexception.initCause(socketexception);
            throw ioexception;
        }
	//从取消key集合中移除已经反注册的取消选择key
        iterator.remove();
        if(true) goto _L2; else goto _L1
_L1:
        break MISSING_BLOCK_LABEL_110;
        Exception exception;
        exception;
        iterator.remove();
        throw exception;
        Exception exception1;
        exception1;
        throw exception1;
    }

 
 //完成SelectionKey的实际反注册工作
    protected abstract void implDereg(SelectionKeyImpl selectionkeyimpl)
        throws IOException;

从processDeregisterQueue方法来看,主要是遍历取消key集合,反注册取消key,实际的
反注册工作由implDereg方法,implDereg方法待子类扩展。
成功,则从集合中移除。

这个方法,待子类实现,我们以后再看
void putEventOps(SelectionKeyImpl selectionkeyimpl, int i)
{
   }

总结:
     SelectorImpl有4个集合分别为就绪key集合,key集合,key集合的代理publicKeys及就绪key集合的代理publicSelectedKeys;实际是两个集合就绪key集合和key集合,publicSelectedKeys和publicKeys是其他线程访问上述两个集合的代理。
     SelectorImpl构造的时候,初始化选择器提供者SelectorProvider,创建就绪key集合和key集合,然后初始化就绪key和key集合的代理,初始化过程为,如果nio包的JDK版本存在bug问题,则就绪key和key集合的代理集合直接引用就绪key和key集合。否则将当前key集合包装成不可修改的代理集合publicKes,将就绪key集合包装成容量固定的集合publicSelectedKeys。
其他线程获取选择器的就绪key和key集合,实际上返回的是key集合的代理publicKeys和就绪key集合的代理publicSelectedKeys。
     select方法的3中操作形式,实际上委托给为lockAndDoSelect方法,方法实际上是同步的,可安全访问,获取key集合代理publicKeys和就绪key代理集合publicSelectedKeys,然后交给doSelect(long l)方法,这个方法为抽象方法,待子类扩展。实际的关闭选择器操作implCloseSelector方法,首先唤醒等待选择操作的线程,唤醒方法wakeup待实现,同步选择器,就绪key和key集合的代理publicKeys,publicSelectedKeys,调用implClose完成实际的关闭通道工作,待子类实现。
     可选通道注册方法,首先注册的通道必须是AbstractSelectableChannel类型,并且是SelChImpl实例。更具可选择通道和选择器构造选择key,设置选择key的附加物,同步key集合代理,调用implRegister方法完成实际的注册工作,implRegister方法待子类实现。
     processDeregisterQueue方法,主要是遍历取消key集合,反注册取消key,实际的反注册工作由implDereg方法,implDereg方法待子类扩展。成功,则从集合中移除。


附:这部分只作为扩展,没有特别的解析,设计,只是贴出代码,有兴趣可以看一下
//VM
package sun.misc;

import java.util.Properties;

// Referenced classes of package sun.misc:
//            OSEnvironment, VMNotification

public class VM
{ 
     private static boolean suspended = false;
    /**
     * @deprecated Field STATE_GREEN is deprecated
     */
    public static final int STATE_GREEN = 1;
    /**
     * @deprecated Field STATE_YELLOW is deprecated
     */
    public static final int STATE_YELLOW = 2;
    /**
     * @deprecated Field STATE_RED is deprecated
     */
    public static final int STATE_RED = 3;
    private static volatile boolean booted = false;
    private static long directMemory = 67108864L;
    private static boolean pageAlignDirectMemory;
    private static boolean defaultAllowArraySyntax;
    private static boolean allowArraySyntax;
    private static final Properties savedProps = new Properties();
    private static volatile int finalRefCount = 0;
    private static volatile int peakFinalRefCount = 0;
    private static final int JVMTI_THREAD_STATE_ALIVE = 1;
    private static final int JVMTI_THREAD_STATE_TERMINATED = 2;
    private static final int JVMTI_THREAD_STATE_RUNNABLE = 4;
    private static final int JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 1024;
    private static final int JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 16;
    private static final int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 32;
    static 
    {
        defaultAllowArraySyntax = false;
        allowArraySyntax = defaultAllowArraySyntax;
        initialize();
    }
    public VM()
    {
    } 
    private static native void initialize();
     public static void booted()
    {
        booted = true;
    }
    public static boolean isBooted()
    {
        return booted;
    }
    public static long maxDirectMemory()
    {
        return directMemory;
    }
    public static boolean isDirectMemoryPageAligned()
    {
        return pageAlignDirectMemory;
    }
     public static void initializeOSEnvironment()
    {
        if(!booted)
            OSEnvironment.initialize();
    }
    public static int getFinalRefCount()
    {
        return finalRefCount;
    }
    public static int getPeakFinalRefCount()
    {
        return peakFinalRefCount;
    }
    public static void addFinalRefCount(int i)
    {
        finalRefCount += i;
        if(finalRefCount > peakFinalRefCount)
            peakFinalRefCount = finalRefCount;
    }
    public static Thread.State toThreadState(int i)
    {
        if((i & 4) != 0)
            return Thread.State.RUNNABLE;
        if((i & 1024) != 0)
            return Thread.State.BLOCKED;
        if((i & 16) != 0)
            return Thread.State.WAITING;
        if((i & 32) != 0)
            return Thread.State.TIMED_WAITING;
        if((i & 2) != 0)
            return Thread.State.TERMINATED;
        if((i & 1) == 0)
            return Thread.State.NEW;
        else
            return Thread.State.RUNNABLE;
    }
    public static boolean allowArraySyntax()
    {
        return allowArraySyntax;
    }
    /**
     * @deprecated Method threadsSuspended is deprecated
     */
    public static boolean threadsSuspended()
    {
        return suspended;
    }
    public static boolean allowThreadSuspension(ThreadGroup threadgroup, boolean flag)
    {
        return threadgroup.allowThreadSuspension(flag);
    }
    /**
     * @deprecated Method suspendThreads is deprecated
     */
    public static boolean suspendThreads()
    {
        suspended = true;
        return true;
    }
    /**
     * @deprecated Method unsuspendThreads is deprecated
     */
    public static void unsuspendThreads()
    {
        suspended = false;
    }
    /**
     * @deprecated Method unsuspendSomeThreads is deprecated
     */
    public static void unsuspendSomeThreads()
    {
    }
    /**
     * @deprecated Method getState is deprecated
     */
    public static final int getState()
    {
        return 1;
    }
    /**
     * @deprecated Method registerVMNotification is deprecated
     */
    public static void registerVMNotification(VMNotification vmnotification)
    {
    
    /**
     * @deprecated Method asChange is deprecated
     */
    public static void asChange(int i, int j)
    {
    }
    /**
     * @deprecated Method asChange_otherthread is deprecated
     */
    public static void asChange_otherthread(int i, int j)
    {
    }
    public static String getSavedProperty(String s)
    {
        if(savedProps.isEmpty())
            throw new IllegalStateException("Should be non-empty if initialized");
        else
            return savedProps.getProperty(s);
    }
    public static void saveAndRemoveProperties(Properties properties)
    {
        if(booted)
            throw new IllegalStateException("System initialization has completed");
        savedProps.putAll(properties);
        String s = (String)properties.remove("sun.nio.MaxDirectMemorySize");
        if(s != null)
            if(s.equals("-1"))
            {
                directMemory = Runtime.getRuntime().maxMemory();
            } else
            {
                long l = Long.parseLong(s);
                if(l > -1L)
                    directMemory = l;
            }
        s = (String)properties.remove("sun.nio.PageAlignDirectMemory");
        if("true".equals(s))
            pageAlignDirectMemory = true;
        s = properties.getProperty("sun.lang.ClassLoader.allowArraySyntax");
        allowArraySyntax = s != null ? Boolean.parseBoolean(s) : defaultAllowArraySyntax;
        properties.remove("java.lang.Integer.IntegerCache.high");
        properties.remove("sun.zip.disableMemoryMapping");
        properties.remove("sun.java.launcher.diag");
    }
}




在代码中经常看到这个语句JVM INSTR monitorenter ;来看一下JVM:
只贴出源码,暂时放在这以后再啃。
class JVM
{
    JVM()
    {
    }
    static long activate(String s, DTraceProvider adtraceprovider[])
    {
        return activate0(s, adtraceprovider);
    }
    static void dispose(long l)
    {
        dispose0(l);
    }
    static boolean isEnabled(Method method)
    {
        return isEnabled0(method);
    }
    static boolean isSupported()
    {
        return isSupported0();
    }
    static Class defineClass(ClassLoader classloader, String s, byte abyte0[], int i, int j)
    {
        return defineClass0(classloader, s, abyte0, i, j);
    }
    private static native long activate0(String s, DTraceProvider adtraceprovider[]);
    private static native void dispose0(long l);
    private static native boolean isEnabled0(Method method);
    private static native boolean isSupported0();
    private static native Class defineClass0(ClassLoader classloader, String s, byte abyte0[], int i, int j);
    static 
    {
        AccessController.doPrivileged(new LoadLibraryAction("jsdt"));
    }
}

来看这一句:
 static 
    {
        AccessController.doPrivileged(new LoadLibraryAction("jsdt"));
    }

jsdt:JavaScript Development Tools (JSDT):
http://www.eclipse.org/webtools/jsdt/
//LoadLibraryAction
package sun.security.action;
import java.security.PrivilegedAction;
public class LoadLibraryAction
    implements PrivilegedAction
{

    public LoadLibraryAction(String s)
    {
        theLib = s;
    }

    public Void run()
    {

       //系统加载lib库
        System.loadLibrary(theLib);
        return null;
    }

    public volatile Object run()
    {
        return run();
    }

    private String theLib;
}

//System
/**
     * Loads the system library specified by the <code>libname</code>
     * argument. The manner in which a library name is mapped to the
     * actual system library is system dependent.
     * <p>
     * The call <code>System.loadLibrary(name)</code> is effectively
     * equivalent to the call
     * <blockquote><pre>
     * Runtime.getRuntime().loadLibrary(name)
     * </pre></blockquote>
     *
     * @param      libname   the name of the library.
     * @exception  SecurityException  if a security manager exists and its
     *             <code>checkLink</code> method doesn't allow
     *             loading of the specified dynamic library
     * @exception  UnsatisfiedLinkError  if the library does not exist.
     * @exception  NullPointerException if <code>libname</code> is
     *             <code>null</code>
     * @see        java.lang.Runtime#loadLibrary(java.lang.String)
     * @see        java.lang.SecurityManager#checkLink(java.lang.String)
     */
    public static void loadLibrary(String libname) {
        Runtime.getRuntime().loadLibrary0(getCallerClass(), libname);
    }








//Runtime
synchronized void loadLibrary0(Class fromClass, String libname) {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkLink(libname);
        }
        if (libname.indexOf((int)File.separatorChar) != -1) {
            throw new UnsatisfiedLinkError(
    "Directory separator should not appear in library name: " + libname);
        }
        ClassLoader.loadLibrary(fromClass, libname, false);
    }





//ClassLoader
// Invoked in the java.lang.Runtime class to implement load and loadLibrary.
    static void loadLibrary(Class fromClass, String name,
                            boolean isAbsolute) {
        ClassLoader loader =
            (fromClass == null) ? null : fromClass.getClassLoader();
        if (sys_paths == null) {
            usr_paths = initializePath("java.library.path");
            sys_paths = initializePath("sun.boot.library.path");
        }
        if (isAbsolute) {
            if (loadLibrary0(fromClass, new File(name))) {
                return;
            }
            throw new UnsatisfiedLinkError("Can't load library: " + name);
        }
        if (loader != null) {
            String libfilename = loader.findLibrary(name);
            if (libfilename != null) {
                File libfile = new File(libfilename);
                if (!libfile.isAbsolute()) {
                    throw new UnsatisfiedLinkError(
    "ClassLoader.findLibrary failed to return an absolute path: " + libfilename);
                }
                if (loadLibrary0(fromClass, libfile)) {
                    return;
                }
                throw new UnsatisfiedLinkError("Can't load " + libfilename);
            }
        }
        for (int i = 0 ; i < sys_paths.length ; i++) {
            File libfile = new File(sys_paths[i], System.mapLibraryName(name));
            if (loadLibrary0(fromClass, libfile)) {
                return;
            }
        }
        if (loader != null) {
            for (int i = 0 ; i < usr_paths.length ; i++) {
                File libfile = new File(usr_paths[i],
                                        System.mapLibraryName(name));
                if (loadLibrary0(fromClass, libfile)) {
                    return;
                }
            }
        }
        // Oops, it failed
        throw new UnsatisfiedLinkError("no " + name + " in java.library.path");
    }









  • 大小: 60.7 KB
  • 大小: 38.5 KB
  • 大小: 54 KB
  • 大小: 31.1 KB
  • 大小: 10.8 KB
  • 大小: 44.9 KB
  • 大小: 60 KB
  • 大小: 54.9 KB
  • 大小: 64.1 KB
1
0
分享到:
评论

相关推荐

    Java NIO——Selector机制解析三(源码分析)

    Java NIO的Selector实现主要由`sun.nio.ch.SelectorImpl`类完成,其内部使用了操作系统提供的多路复用I/O机制,如Linux的epoll、Windows的IOCP等。`select()`方法实际上会调用操作系统API,阻塞等待直到有事件发生。...

    flink-table-api-java-1.12.4.jar中文-英文对照文档.zip

    # 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    基于MPC的微网共享储能日前日内优化调度技术及其实现

    内容概要:本文详细探讨了基于模型预测控制(MPC)的微网共享储能优化调度技术,分为日前优化和日内滚动MPC跟踪两大部分。日前优化部分通过分析居民用电需求,制定储能充放电策略,确保整体能源利用效率最大化。日内滚动MPC跟踪部分则通过预测模型、滚动优化和反馈校正,动态调整储能状态,保持系统稳定。文中提供了多个Python和MATLAB代码片段,展示了具体的技术实现细节,如K-means聚类、CVXPY建模、LSTM+ARIMA混合预测等。 适合人群:从事微网系统设计、储能优化调度的研究人员和技术开发者,以及对模型预测控制感兴趣的工程技术人员。 使用场景及目标:适用于微网系统的储能管理,旨在提高能源利用效率、降低运营成本,并确保系统在各种工况下的稳定性。主要目标是通过合理的储能调度,实现削峰填谷和平抑负荷波动。 其他说明:文章不仅介绍了理论背景,还分享了实际应用中的经验和教训,如处理光伏出力预测误差、优化求解器性能等问题。同时,文中提到的一些关键技术点,如充放电互斥约束、终端约束等,有助于深入理解MPC的应用挑战和解决方案。

    未来互联网:元宇宙、Web3.0与区块链的变革力量

    本书由Bernard Marr撰写,探讨了互联网的第三次演变——未来互联网,即Web 3.0和元宇宙的概念。作者详细分析了元宇宙技术、Web3和区块链如何共同作用,推动互联网向更沉浸式和去中心化的方向发展。书中指出,这一变革不仅将改变我们的日常生活和娱乐方式,还将深刻影响教育、金融、医疗保健以及制造业等多个行业。同时,作者也探讨了政府和公共服务如何利用未来互联网提高效率,以及企业如何在这一变革中重新思考产品、服务和业务运营。书中还强调了未来互联网对技能需求的影响,以及如何在企业中建立适应未来互联网的成功文化,并制定相应的战略。

    flink-connector-jdbc_2.12-1.13.6.jar中文-英文对照文档.zip

    # 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    FPGA中基于VHDL的16阶FIR低通滤波器设计与实现

    内容概要:本文详细介绍了如何使用VHDL语言在FPGA上实现16阶FIR低通滤波器的设计与实现。首先,文中给出了滤波器的基本参数设定,如采样率为50MHz,截止频率为3MHz,并采用汉明窗进行设计。接着,展示了顶层实体声明及其内部逻辑结构,包括移位寄存器作为延迟线以及乘累加操作的具体实现方法。同时提供了完整的VHDL代码片段,涵盖了从顶层实体定义到具体的功能模块,如系数生成、数据移位寄存器和乘累加模块。此外,还讨论了ModelSim仿真的配置与测试激励生成方式,确保仿真结果能够正确反映滤波器性能。最后,针对硬件实现过程中可能出现的问题进行了提示,如时钟约束、资源优化等。 适合人群:具有一定FPGA开发经验的技术人员,尤其是对VHDL编程有一定了解并希望深入研究FIR滤波器实现的人群。 使用场景及目标:适用于需要在FPGA平台上快速搭建并验证FIR低通滤波器的应用场合。主要目标是帮助开发者掌握FIR滤波器的工作原理及其在FPGA上的高效实现方法。 其他说明:文中不仅提供了详细的代码示例,还包括了许多实用的经验分享和技术要点提醒,有助于提高开发效率并减少常见错误的发生。

    车辆紧急防避撞AEB控制系统:基于模糊控制与逆动力学模型的仿真与代码解析

    内容概要:本文详细介绍了车辆紧急防避撞AEB控制系统的构建与实现。首先,文章阐述了驾驶员制动模型,通过模拟人类驾驶者的制动行为,使车辆能够根据实际情况做出适当的制动反应。其次,引入了模糊控制方法用于计算期望减速度,使得车辆能够在面对不确定性环境时作出智能化决策。再次,建立了纵向发动机逆动力学模型,以确定合适的节气门开度,确保车辆的动力输出满足制动需求。此外,还探讨了制动压力与减速度的关系以及风阻和滚动阻力的影响,并展示了具体的代码实现。最后,文章描述了仿真的步骤,强调了验证模型有效性的重要性。 适合人群:从事自动驾驶技术研发的专业人士、对车辆控制感兴趣的工程师和技术爱好者。 使用场景及目标:适用于研究和开发先进的车辆安全辅助系统,旨在提高车辆在紧急情况下的避撞能力,减少交通事故的发生。通过理解和应用文中提供的模型和代码,可以为实际工程项目提供理论支持和技术指导。 其他说明:文章不仅提供了详细的理论解释,还包括了大量的代码示例,便于读者理解和实践。同时,作者还分享了一些实际开发中的经验和技巧,有助于解决可能出现的问题并优化系统性能。

    Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码

    Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码,个人经导师指导并认可通过的高分设计项目,评审分99分,代码完整确保可以运行,小白也可以亲自搞定,主要针对计算机相关专业的正在做大作业的学生和需要项目实战练习的学习者,可作为毕业设计、课程设计、期末大作业,代码资料完整,下载可用。 Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源

    基于 Python 和 Selenium 的完整网页自动化脚本工具案例,用于模拟用户登录一个示例网站、获取用户信息并退出登录(由于实际网站的结构和元素可能不同,实际使用时需要根据目标网站进行调整)

    脚本功能: 自动打开浏览器。 进入指定的登录页面。 输入预设的用户名和密码。 点击登录按钮。 登录成功后获取用户信息并打印。 点击退出按钮并退出登录。 关闭浏览器。 注意事项: 确保已安装适用于您浏览器的驱动程序,例如 ChromeDriver,并正确设置其路径。 在实际应用中,您需要根据目标网站的结构和元素修改选择器(如 By.NAME、By.ID 等)和相应的值。 此脚本仅为示例,实际使用时需要考虑更复杂的场景,例如异常处理、验证码处理、动态元素加载等。 遵守目标网站的使用条款和法律法规,不要用于非法或未经授权的操作。

    groovy-2.2.2.jar中文文档.zip

    # 压缩文件中包含: 中文文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    【信息安全领域实战项目】

    【信息安全领域实战项目】

    groovy-2.4.15.jar中文文档.zip

    # 压缩文件中包含: 中文文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    基于滑膜控制的五车编队自适应协同巡航仿真与模型研究

    内容概要:本文探讨了基于滑膜控制的五辆车编队实现自适应协同巡航控制(ACC)的研究。通过carsim/Simulink平台进行仿真,采用分层控制结构,上层滑膜控制器根据前车的距离和速度误差计算期望加速度,下层则通过控制节气门开度和制动压力来实现车速控制。文中展示了详细的算法架构、关键代码片段以及丰富的仿真结果图,验证了滑膜控制在车辆编队中的优越性能,特别是在紧急情况下能够迅速反应并保持稳定的跟车距离。 适合人群:对自动驾驶技术和车辆控制系统感兴趣的科研人员、工程师及高校相关专业学生。 使用场景及目标:适用于研究和开发多车编队的自适应巡航控制系统,旨在提高车队行驶的安全性和效率。具体目标包括减少车速跟踪误差、优化节气门和制动控制、提升紧急情况下的响应速度。 其他说明:提供了详细的滑膜控制理论讲解和技术实现细节,附带完整的仿真数据和工程落地指导,有助于读者深入理解和应用该技术。

    flink-table-common-1.13.3.jar中文-英文对照文档.zip

    # 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    三相桥式整流电路双闭环控制系统设计与MATLAB仿真

    内容概要:本文详细介绍了三相桥式整流电路采用双闭环控制(电流内环和电压外环)的方法及其在MATLAB中的仿真实现。首先阐述了为何需要引入电流内环来提高系统的动态响应速度和稳定性,特别是在负载突变情况下。接着描述了硬件配置,包括六个晶闸管的工作方式以及触发脉冲的生成机制。文中给出了具体的双PI控制器参数设置方法,并展示了如何通过调整电流环和电压环的比例和积分系数来优化系统性能。此外,还讨论了常见的调试问题及解决方案,如同步触发信号的相位补偿、PI参数的选择、采样时间的影响等。最后通过仿真实验数据对比,证明了双闭环控制相比单环控制在稳定性和抗干扰方面有着显著优势。 适合人群:从事电力电子研究的技术人员、高校相关专业师生、对电力电子控制系统感兴趣的工程技术人员。 使用场景及目标:适用于需要深入了解三相桥式整流电路双闭环控制原理并进行仿真实践的学习者;旨在帮助读者掌握双闭环控制系统的参数选择、调试技巧及应用实例。 其他说明:文中提供了大量MATLAB代码片段用于辅助理解和实施具体控制策略,同时分享了许多来自实际项目的经验教训,有助于读者更好地将理论应用于实践中。

    基于Matlab的飞蛾扑火优化算法(MFO)详解及其23个测试函数应用

    内容概要:本文详细介绍了飞蛾扑火优化算法(Moth Flame Optimization, MFO)的原理和实现方法。首先解释了MFO的基本概念,即通过模仿飞蛾绕光飞行的行为来构建优化算法。接着展示了MFO的关键公式和Matlab代码实现,特别是飞蛾位置更新公式的具体形式。文中提供了23个经典的测试函数用于评估MFO性能,并给出了具体的调用方式。此外,还讨论了算法运行效果以及一些重要的调参经验和技巧,如种群数量、迭代次数、边界设定等。最后分享了一个实际应用案例,展示了MFO在光伏电池板排布优化中的成功应用。 适合人群:对优化算法感兴趣的科研工作者、学生以及从事相关领域研究的专业人士。 使用场景及目标:适用于需要高效求解复杂优化问题的研究项目,尤其是涉及多峰函数优化的情况。目标是帮助读者掌握MFO的工作原理并能够独立应用于实际问题中。 其他说明:本文不仅提供了详细的理论讲解和技术细节,还包括完整的代码实现和丰富的实验数据,有助于深入理解和实践MFO算法。

    一个通用的数据库管理工具和SQL客户端,具有许多功能,包括元数据编辑器、SQL 编辑器、富数据编辑器、ERD、数据导出/导入/迁移、SQL 执行计划等

    DBeaver 是一个通用的数据库管理工具和 SQL 客户端,具有许多功能,包括元数据编辑器、SQL 编辑器、富数据编辑器、ERD、数据导出/导入/迁移、SQL 执行计划等。支持 MySQL, PostgreSQL, Oracle, DB2, MSSQL, Sybase, Mimer, HSQLDB、Derby、Teradata、Vertica、Netezza、Informix 等。

    永磁同步电机降阶负载转矩观测器及其前馈补偿的应用研究

    内容概要:本文详细探讨了永磁同步电机(PMSM)中采用降阶负载转矩观测器进行转矩估计的方法,并介绍了将估计得到的负载转矩用于前馈补偿的技术。首先,文章指出传统全阶观测器存在模型复杂、参数调整困难的问题,提出利用降阶观测器简化模型并提高参数调整效率。接着,通过具体的数学推导和MATLAB/Simulink代码展示了降阶观测器的设计过程,强调了关键参数如观测器增益的选择对系统性能的影响。然后,讨论了前馈补偿的具体实现方式,即在速度环输出中加入负载转矩估计值,从而有效减小突加负载引起的转速波动。最后,通过实验数据对比证明了该方法的有效性和优越性,尤其是在应对突加负载时的表现更为突出。 适合人群:从事电机控制领域的研究人员和技术人员,尤其是关注永磁同步电机控制策略优化的专业人士。 使用场景及目标:适用于需要精确控制永磁同步电机转矩的应用场合,如电梯、电动汽车等。目标是提高系统的抗干扰能力和稳定性,减少突加负载导致的转速波动。 其他说明:文中提供了详细的MATLAB和C语言代码示例以及仿真模型构建指南,有助于读者理解和实践所介绍的技术。此外,还分享了一些实用的工程经验和调试技巧,如参数设置范围、注意事项等。

    西门子1200 PLC水处理系统:SCL编程实现模拟量换算、滤波、时间换算及Modbus TCP通讯

    内容概要:本文详细介绍了西门子1200 PLC在水处理系统中的应用,重点讲解了SCL编程实现的关键功能块,包括模拟量换算、滤波、时间换算以及Modbus TCP通讯程序。每个功能块都有详细的代码示例和应用场景说明,展示了如何将模拟量信号转换为数字量、去除信号噪声、进行时间单位换算以及实现设备间的高效通信。此外,文中还提到了一些实用技巧,如仿真环境搭建、电气原理图解读、HMI界面设计等。 适合人群:具备一定PLC编程基础的技术人员,尤其是从事水处理行业自动化控制领域的工程师。 使用场景及目标:① 学习如何利用SCL语言编写高效的PLC功能块;② 掌握水处理系统中常见的信号处理方法;③ 实现PLC与其他设备之间的可靠通信;④ 提升对复杂工业控制系统的设计和调试能力。 其他说明:文中不仅提供了理论知识,还分享了许多实际项目中的经验和优化技巧,帮助读者更好地理解和应用所学内容。

    永磁同步电机无感FOC控制源码解析及磁链观测器实现

    内容概要:本文详细介绍了永磁同步电机和直流无刷电机无感FOC(磁场定向控制)的源码及其关键技术。首先探讨了速度与位置估算代码的设计,展示了如何使用实际值单位使代码更加直观。接着介绍了基于TI FOC框架的磁链观测器,强调了其开源性质和详细的注释,便于理解和扩展。此外,文章还提到了雅特力AT32平台的工程源码,以及电流环PI参数自动计算功能,显著提升了开发效率。最后,讨论了优秀的启动性能,如静止闭环启动、快速角度收敛、PLL锁相环的速度角度跟踪和鲁棒性强的特点。 适合人群:电机控制领域的工程师和技术爱好者,尤其是那些希望深入了解无感FOC控制机制并应用于实际项目的人群。 使用场景及目标:适用于需要高效、稳定的电机控制系统的设计和开发。目标是帮助读者掌握无感FOC控制的核心技术和实现方法,提高系统的响应速度和稳定性。 其他说明:文中提供的代码示例和解释有助于读者更好地理解无感FOC的工作原理,并提供了一种高效的开发方式,减少了调试时间和成本。

Global site tag (gtag.js) - Google Analytics